1
votes

I have a class with a property which is a weak reference to a block.

@interface BlockTest : NSObject
    @property (nonatomic, weak) void(^testBlock)();
@end

At another point in the class I use this block like this:

- (void)foobar {
    self.testBlock = ^{
        [self doSomething];
    };
}

The compiler (Apple LLVM 3.0) complains that there might be a retain cycle because self is strongly captured here. But I fail to see how this leads to a retain cycle because the block itself is a __weakreference, so it should be fine. If I understood ARC weak references correctly, when the -foobar method returns the block passed to self.testBlock should be deallocated (if not held elsewhere) and thus also release self.

What's the reason the compiler still thinks there might be a retain cycle?

1
The setup you have is pretty much useless. The block will be immediately deallocated after the function exits, since there are no strong references to it. The property will be nil. - newacct
That's not universally true. Global and stack blocks won't be retained or released and therefore are still valid after the assignment (for stack blocks until the end of the current scope). Also that's just a sample. The idea was not to keep the block around or anything. IIRC When I asked this question I was looking for a way to capture self in a callback block of a method called on self without triggering the warning. - Alfonso

1 Answers

8
votes

Blocks strongly capture objects within them regardless of how the block itself is referenced. The retain cycle warning is just that, a warning of the possibility. If you know based on the context of your app that this use will not cause a retain cycle you can safely ignore it. To get rid of the warning, you can pass self through an intermediary, strong or weak, as follows:

__weak typeof(self) weakSelf = self;
self.testBlock = ^{
    [weakSelf doSomething];
};

I'd change your block property to be a strong reference and do the above.