Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 圆弧中的递归块和保留循环_Objective C_Recursion_Automatic Ref Counting_Objective C Blocks_Retain Cycle - Fatal编程技术网

Objective c 圆弧中的递归块和保留循环

Objective c 圆弧中的递归块和保留循环,objective-c,recursion,automatic-ref-counting,objective-c-blocks,retain-cycle,Objective C,Recursion,Automatic Ref Counting,Objective C Blocks,Retain Cycle,编辑2: 不是。建议的答案是关于异步调用。我需要同步调用,就像在普通的、标准的递归调用中一样 编辑: 当 编译时没有警告或错误,它在运行时失败,NULL存储在不安全的应用程序中 然而,这: - (void) applyToView: (UIView *) view { UIColor * (^colorForIndex)(NSInteger) = ^(NSInteger index) { return [UIColor colorWithHue: ((CGFloat)

编辑2:

不是。建议的答案是关于异步调用。我需要同步调用,就像在普通的、标准的递归调用中一样

编辑:

编译时没有警告或错误,它在运行时失败,NULL存储在不安全的应用程序中

然而,这:

- (void) applyToView: (UIView *) view {

    UIColor * (^colorForIndex)(NSInteger) = ^(NSInteger index) {
        return [UIColor colorWithHue: ((CGFloat) index / 255.0f)
                          saturation: 0.5f
                          brightness: 0.5f
                               alpha: 1.0f] ;
    } ;

    void (^applyColors) (UIView *, NSInteger index) = ^(UIView * view, NSInteger index) {
        view.backgroundColor = colorForIndex(index) ;
    } ;

    void (^__block recurse_apply)(UIView *, NSInteger) ;

    void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
        applyColors(view, level) ;
        [view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
            recurse_apply(subview, 1+level) ;
        }] ;
    } ;

    recurse_apply = apply ;

    apply(view, 0) ;
}
编译时没有警告,但更重要的是,实际运行

但是这太难看了


考虑(为视图层次着色,用于显示目的…):

我得到这个警告:

/Users/verec/Projects/solotouch/solotouch/BubbleMenu.m:551:42:
块指针变量“apply”在被块捕获时未初始化

如果我应用了建议的修复:
也许你想使用u块“apply”

void (^__block apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
然后我得到:/Users/verec/Projects/solotouch/solotouch/BubbleMenu.m:554:13:
在这个块中强烈地捕获“apply”很可能会导致一个保留周期

我尝试了各种方法来篡改代码并消除这些警告

__weak typeof (apply) wapply = apply ;
if (wapply) {
    __strong typeof (wapply) sappy = wapply ;
    wapply(subview, 1+level) ;
}
但事情只会变得更糟,变成错误

我的结局是:

__unsafe_unretained void (^unsafe_apply)(UIView *, NSInteger) ;

void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
    applyColors(view, level) ;
    [view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
        unsafe_apply(subview, 1+level) ;
    }] ;
} ;

unsafe_apply = apply ;

apply(view, 0) ;
任何人都有更好的解决方案,我可以在区块内做任何事情,而不是像我在这里做的那样可怕地修补它

请注意,这些是关于捕获自己的,而那些没有任何令人满意的答案。

答案是否定的

我们似乎没有比使用_块限定符更好的了

__block void(^strawberryFields)();
strawberryFields = ^{ strawberryFields(); };
strawberryFields();
感谢关于积木的文章


编辑:


似乎是ARC下的首选方式。

您需要捕获一个
\u块
变量,因为块在创建时按值捕获非
\u块
变量,并且赋值在创建块后发生

在ARC中,对象指针类型的
\u块
变量(通常所有变量都隐式地
\u strong
)由块保留。因此,如果块捕获指向自身的
\u块
变量,它将创建一个保留循环。解决方案是让它捕获弱引用。在支持
\uuu弱
的操作系统版本中,应使用
\uu弱
而不是
\uu不安全的

但是,如果对块的唯一引用是
\uu弱
变量,则不会有对块的强引用,这意味着它可以被释放。为了使用块,它必须有一个强大的参考,以保持其周围

因此,您需要两个变量,一个弱变量和一个强变量。在ARC中执行此操作的正确方法是:

__block __weak void (^weak_apply)(UIView *, NSInteger) ;
void (^apply)(UIView *, NSInteger) ;
weak_apply = apply = ^(UIView * view, NSInteger level) {
    applyColors(view, level) ;
    [view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
        weak_apply(subview, 1+level) ;
    }] ;
} ;

apply(view, 0) ;

为了避免ARC警告并基于@newacct的答案,我发现在保留块中设置弱块是有效的:

//a block definition
typedef void (^CompletionType)(NSDictionary * __nullable response, NSError * __nullable error);


//a block calling itself without the ARC retain warning
__block CompletionType completionBlock = nil;
__block __weak CompletionType weakCompletionBlock = nil;
completionBlock = ^(NSDictionary *response, NSError *error) {
    weakCompletionBlock = completionBlock;

        weakCompletionBlock();

    });
};

像我的编辑?但必须支持补丁确实很难看,而且容易出错。是否有一些正常的、标准的方法来使用递归块?特别是可能的重复,请参见否!提到的问题是关于异步调用的。我需要常规的、普通的、标准的递归调用。不涉及线程。该解决方案适用于任何递归块。你试过了吗?你是认真的吗?您所指的“解决方案”有两种方法,20多行代码,并且是异步的!我已经很难过,我自己的版本有3行不必要的行,你会建议我添加更多的混乱,而结果取决于GCD???这段代码早于ARC;从那时起,
\u块
的效果发生了变化,在不使用
\u弱
的情况下使用它会创建一个保留周期:
\u块\u弱
得到警告将块文字赋值给弱变量;对象将在Xcode 5下的赋值`后释放。。。。所以这似乎也不是正确的答案???分两步进行:
\u弱空(^weak\u block)()
后跟
u块void(^strong_u块)(=^(){if(无论什么)弱_u块();}
,最后添加:
弱块=强块
strong_block
的主体之后。当我使用最新版本的Xcode尝试此操作时,编译器会用一个警告标记它:“将块文字赋值给弱变量;赋值后将释放对象”。由于您的方法正是围绕这一点工作的,所以我认为忽略警告是安全的。你知道如何关闭它吗?@Drux:更改了分配顺序我已经用XCode 6测试过了,但是如果我在块中添加分配,内存将不会被释放:|但是
completionBlock
是一个强持有对象,它本身有一个对
completionBlock
的强持有引用。因此,您得到了一个保留周期,这与您消除了所有提及的
weakCompletionBlock
完全相同。
__block __weak void(^strawberryFields)();
__block __weak void (^weak_apply)(UIView *, NSInteger) ;
void (^apply)(UIView *, NSInteger) ;
weak_apply = apply = ^(UIView * view, NSInteger level) {
    applyColors(view, level) ;
    [view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
        weak_apply(subview, 1+level) ;
    }] ;
} ;

apply(view, 0) ;
//a block definition
typedef void (^CompletionType)(NSDictionary * __nullable response, NSError * __nullable error);


//a block calling itself without the ARC retain warning
__block CompletionType completionBlock = nil;
__block __weak CompletionType weakCompletionBlock = nil;
completionBlock = ^(NSDictionary *response, NSError *error) {
    weakCompletionBlock = completionBlock;

        weakCompletionBlock();

    });
};