I've read over this thread: What does the "__block" keyword mean? which discusses what __block
is used for but I'm confused about one of the answers. It says __block
is used to avoid retain cycles, but the comments underneath it leave me unsure.
I'm using it something like this:
self.someProperty = x; //where x is some object (id) __block __weak VP_User *this = self; //begin a callback-style block this.someProperty = nil;
Do I need to use both __block
and __weak
? Any glaring problems with this way this looks?
The __block Storage Type __block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable's lexical scope.
__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
Weak blocks are blocks that does not appear in the blockchain, only in the p2p network. Miners produce these blocks with reduced difficulty, for example 1/20 of the strong block target difficulty.
__block
is a storage qualifier. It specifies that the variable should directly be captured by the block as opposed to copying it. This is useful in case you need to modify the original variable, as in the following example
__block NSString *aString = @"Hey!"; void(^aBlock)() = ^{ aString = @"Hello!" }; // without __block you couldn't modify aString NSLog(@"%@", aString); // Hey! aBlock(); NSLog(@"%@", aString); // Hello!
In ARC this causes the variable to be automatically retained, so that it can be safely referenced within the block implementation. In the previous example, then, aString
is sent a retain
message when captured in the block context.
Note that this isn't true in MRC (Manual Reference Counting), where the variable is referenced without being retained.
Marking it as __weak
causes the variable not to be retained, so the block directly refers to it but without retaining it. This is potentially dangerous since in case the block lives longer than the variable, since it will be referring to garbage memory (and likely to crash).
Here's the relevant paragraph from the clang doc:
In the Objective-C and Objective-C++ languages, we allow the
__weak
specifier for__block
variables of object type. [...] This qualifier causes these variables to be kept without retain messages being sent. This knowingly leads to dangling pointers if the Block (or a copy) outlives the lifetime of this object.
Finally the claim that __block
can be used to avoid strong reference cycles (aka retain cycles) is plain wrong in an ARC context. Due to the fact that in ARC __block
causes the variable to be strongly referenced, it's actually more likely to cause them.
For instance in MRC this code breaks a retain cycle
__block typeof(self) blockSelf = self; //this would retain self in ARC! [self methodThatTakesABlock:^ { [blockSelf doSomething]; }];
whereas to achieve the same result in ARC, you normally do
__weak typeof(self) weakSelf = self; [self methodThatTakesABlock:^ { [weakSelf doSomething]; }];
You should use __block
if you want to change variable value in block.
e.g:
__block BOOL result = NO; dispatch_sync(dispatch_get_main_queue(), ^{ ... result = YES; ... });
You should use __weak
if you want to avoid retain cycles.
e.g.:
__weak typeof(self) wself = self; self.foobarCompletion = ^{ ... wself.foo = YES; ... };
You can combine them if there is a need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With