In your example it's not strictly necessary to make a strong reference inside the block again: weakFoo
will either be nil
and the method is not called, or it's a valid reference and will stay valid for the duration of this call.
But consider the following snippet:
Foo *foo = [Foo new];
__weak Foo *weakFoo = foo;
foo.aBlock = ^{
[weakFoo bar];
[weakFoo baz];
}
... then somewhere later use foo.aBlock()
Now you introduced a race condition, where weakFoo
could be valid for the first call, but nil
for the second call. This is almost never what you want. In this case use __strong Foo *foo = weakFoo;
to make sure you have the same value for both calls.
Edit:
Here is an example how you can trigger such a race condition:
@interface BlockHolder : NSObject
@property (nonatomic, copy) void(^block)(void);
@end
@implementation BlockHolder
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
BlockHolder *holder = [[BlockHolder alloc] init];
__weak BlockHolder *weakHolder = holder;
holder.block = ^{
for (int i = 0; i < 10; i++) {
NSLog(@"weakHolder is %@", weakHolder);
sleep(1);
}
};
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, holder.block);
sleep(2); // give the queue some time to start executing the block
holder = nil;
dispatch_sync(queue, ^{}); // wait for the queue to finish
}
return 0;
}