recursive block and retain cycles in ARC

只谈情不闲聊 提交于 2019-11-29 21:01:52

You need to capture a __block variable, because blocks capture non-__block variables by value when they are created, and the assignment happens after the block has been created.

In ARC, __block variables of object pointer type (generally all variables are implicitly __strong) are retained by the block. So if the block captures a __block variable pointing to itself, it would create a retain cycle. The solution is to have it capture a weak reference. In versions of the OS that support __weak, __weak should be used instead of __unsafe_unretained.

However, if the only reference to the block was a __weak variable, there would be no strong references to the block, which means it can be deallocated. In order to use the block, it must have a strong reference to keep it around.

Therefore, you need two variables, one weak and one strong. The proper way to do it in ARC is:

__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) ;

To avoid ARC warnings and building on @newacct 's answer, I found that setting the weak block inside the retained block works:

//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();

    });
};

The answer is no.

We can't seem to do better than using the __block qualifier.

__block void(^strawberryFields)();
strawberryFields = ^{ strawberryFields(); };
strawberryFields();

Thanks to Bill Bumgarner article about blocks.


EDIT:

__block __weak void(^strawberryFields)();

seems to be the preferred way under ARC.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!