Blocks and self from called method - objective-c

Ok, so I understand how to avoid self retain cycles with blocks, how about cases when I send a message to self from a method within a block nested deeper in call stack like this:
- (void)methodA {
__block MyClass *blockSelf = self;
[someObject block:^{
[blockSelf methodB];
}];
}
- (void)methodB {
...
[self methodC];
...
}
- (void)methodC {
}
In this case [blockSelf methodB] is fine, but is sending [self methodC] from methodB causing retain cycle or not? Can't find the answer anywhere...

There’s no retain cycle there. When a Block literal is defined inside a method, the context that can be captured by the Block is limited to what is visible inside that method. In your example:
- (void)methodA {
__block MyClass *blockSelf = self;
[someObject block:^{
[blockSelf methodB];
}];
}
the Block literal, namely:
^{
[blockSelf methodB];
}
is able to see the following:
self and _cmd, which are hidden parameters available in every Objective-C method. If -methodA had formal parameters, the Block literal would be able to see them, too;
Any block-scope variables inside the function/method block, i.e., every local variable inside the method and which is visible at the point where the Block literal is defined. In the example, the only local variable inside -methodA is blockSelf which, because it’s __block-qualified, is not retained;
Any file-scope variables (aka global variables).
A Block literal is unaware (and, in the general case, cannot be aware) of what happens inside other functions/methods, hence whatever context is available inside called functions/methods is not captured by the Block literal. You only need to worry about the method where the Block literal is defined.
I’m using Apple’s convention of capitalising Block when referring to closures/lambdas (i.e., ^{}) and lowercase block when referring to C blocks (i.e., {}).

Related

Objective-C define block after passing it to a method

Is it possible to define a block after passing it to a method? I want to do this so the code is in somewhat the order it runs in:
// Declare the block
void (^doStuffBlock)(void);
// Pass the block.
[self prepareToDoStuffWithCompletion:doStuffBlock];
// Define the block.
doStuffBlock = ^void() {
// Do stuff
};
doesn't work because inside prepareToDoStuffWithCompletion: the block doStuffBlock is nil.
you should first define the block then pass it to the method:
// Declare the block
void (^doStuffBlock)(void);
// Define the block.
doStuffBlock= ^void() {
// Do stuff
};
// Pass the block.
[self prepareToDoStuffWithCompletion:doStuffBlock];
You could use a typedef.
typedef void (^TypeName)(void);
- (void)bar:(TypeName)completion {
completion();
}
TypeName foo = ^() { /*...*/ };
[self bar:foo];
(My obj-c syntax might be a little rusty, but what you want to do is possible in both Objective-C and Swift.
https://stackoverflow.com/a/29580490/620197
http://goshdarnblocksyntax.com/
If you are certain that the method will run your doStuffBlock after you "define" it, what you could do is have your doStuffBlock capture a variable holding a second block with the real logic of what it should do. You can set the real-logic block after you create doStuffBlock, and you need to make sure that the variable holding the real-logic block is a __block variable, so that changes to the variable in the function scope are seen in the block scope.
__block void (^realLogicBlock)(void);
[self prepareToDoStuffWithCompletion:^{
if (realLogicBlock)
realLogicBlock();
}];
realLogicBlock = ^void() {
// Do stuff
};
You might have to be careful about retain cycles though -- if inside realLogicBlock, you capture a reference to self or to something that will reference the prepareToDoStuffWithCompletion: completion handler, you would have a retain cycle, in which case you may have to introduce a weak reference somewhere.
If you supply the completion handler closure, you are effectively saying “here is the closure I want you to use”.
If you are going to supply the closure later you would probably define a property:
#property (nonatomic, copy, nullable) void (^doStuff)(void);
Then, do not supply the closure when you call the method, but rather refer to this property:
- (void)prepareToDoStuff {
[self somethingAsynchronousWithCompletion:^{
if (self.doStuff) {
self.doStuff();
// if completion handler, you’d often release it when done, e.g.
//
// self.doStuff = nil;
}
}];
}
And, then you can call this method and supply the closure later:
[self prepareToDoStuff];
self.doStuff = ^{
NSLog(#"do stuff done");
};
A few additional considerations:
Make sure you synchronize your access to this doStuff property. E.g., in the above, I am assuming that the somethingAsynchronousWithCompletion is calling its completion handler on the main thread. If not, synchronize your access (like you would any non-thread-safe property in a multithreaded environment).
There is a logical race if you first call the method that will eventually call the block, and only later set that block property. Sometimes that is perfectly fine (e.g. maybe you are just trying to specify what UI to update when the asynchronous process finishes). Other times, the race can bite you. It depends upon the functional intent of the block property.
I would give the block property a name that better reflects its functional purpose (e.g. completionHandler or notificationHandler or didReceiveValue or whatever).

Objective-C block "retain cycle" warning, don't understand why

I've seen several other questions of the same form, but I either a) can't understand the provided answers, or b) don't see how those situations are similar to mine.
I'm writing a Category on UIView to recursively evaluate all the subviews of a UIView and return an Array of subviews passing a test. I've noted where my compiler warning occurs:
-(NSArray*)subviewsPassingTest:(BOOL(^)(UIView *view, BOOL *stop))test {
__block BOOL *stop = NO;
NSArray*(^__block evaluateAndRecurse)(UIView*);
evaluateAndRecurse = ^NSArray*(UIView *view) {
NSMutableArray *myPassedChildren = [[NSMutableArray alloc] init];
for (UIView *subview in [view subviews]) {
BOOL passes = test(subview, stop);
if (passes) [myPassedChildren addObject:subview];
if (stop) return myPassedChildren;
[myPassedChildren addObjectsFromArray:evaluateAndRecurse(subview)];
// ^^^^ Compiler warning here ^^^^^
// "Capturing 'evaluateAndRecurse' strongly in this block
// is likely to lead to a retrain cycle"
}
return myPassedChildren;
};
return evaluateAndRecurse(self);
}
Also, I get a bad_access failure when I don't include the __block modifier in my block's declaration (^__block evaluateAndRecurse). If someone could explain why that is, that would be very helpful too. Thanks!
The problem here is that your block evaluteAndRecurse() captures itself, which means that, if it's ever to be copied (I don't believe it will in your case, but in slightly less-trivial cases it may), then it will retain itself and therefore live forever, as there is nothing to break the retain cycle.
Edit: Ramy Al Zuhouri made a good point, using __unsafe_unretained on the only reference to the block is dangerous. As long as the block remains on the stack, this will work, but if the block needs to be copied (e.g. it needs to escape to a parent scope), then the __unsafe_unretained will cause it to be deallocated. The following paragraph has been updated with the recommended approach:
What you probably want to do here is use a separate variable marked with __unsafe_unretained that also contains the block, and capture that separate variable. This will prevent it from retaining itself. You could use __weak, but since you know that the block must be alive if it's being called, there's no need to bother with the (very slight) overhead of a weak reference. This will make your code look like
NSArray*(^__block __unsafe_unretained capturedEvaluteAndRecurse)(UIView*);
NSArray*(^evaluateAndRecurse)(UIView*) = ^NSArray*(UIView *view) {
...
[myPassedChildren addObjectsFromArray:capturedEvaluateAndRecurse(subview)];
};
capturedEvaluateAndRecurse = evaluteAndRecurse;
Alternatively, you could capture a pointer to the block, which will have the same effect but allow you to grab the pointer before the block instantiation instead of after. This is a personal preference. It also allows you to omit the __block:
NSArray*(^evaluateAndRecurse)(UIView*);
NSArray*(^*evaluteAndRecursePtr)(UIView*) = &evaluateAndRecurse;
evaluateAndRecurse = ^NSArray*(UIView*) {
...
[myPassedChildren addObjectsFromArray:(*evaluateAndRecursePtr)(subview)];
};
As for needing the __block, that's a separate issue. If you don't have __block, then the block instance will actually capture the previous value of the variable. Remember, when a block is created, any captured variables that aren't marked with __block are actually stored as a const copy of their state at the point where the block is instantiated. And since the block is created before it's assigned to the variable, that means it's capturing the state of the capturedEvaluteAndRecurse variable before the assignment, which is going to be nil (under ARC; otherwise, it would be garbage memory).
In essence, you can think of a given block instance as actually being an instance of a hidden class that has an ivar for each captured variable. So with your code, the compiler would basically treat it as something like:
// Note: this isn't an accurate portrayal of what actually happens
PrivateBlockSubclass *block = ^NSArray*(UIView *view){ ... };
block->stop = stop;
block->evaluteAndRecurse = evaluateAndRecurse;
evaluteAndRecurse = block;
Hopefully this makes it clear why it captures the previous value of evaluateAndRecurse instead of the current value.
I've done something similar, but in a different way to cut down on time allocating new arrays, and haven't had any problems. You could try adapting your method to look something like this:
- (void)addSubviewsOfKindOfClass:(id)classObject toArray:(NSMutableArray *)array {
if ([self isKindOfClass:classObject]) {
[array addObject:self];
}
NSArray *subviews = [self subviews];
for (NSView *view in subviews) {
[view addSubviewsOfKindOfClass:classObject toArray:array];
}
}

Why do we have to set __block variable to nil?

From the Transitioning to ARC Release Notes
Use Lifetime Qualifiers to Avoid Strong Reference Cycles
You can use lifetime qualifiers to avoid strong reference cycles. For
example, typically if you have a graph of objects arranged in a
parent-child hierarchy and parents need to refer to their children and
vice versa, then you make the parent-to-child relationship strong and
the child-to-parent relationship weak. Other situations may be more
subtle, particularly when they involve block objects.
In manual reference counting mode, __block id x; has the effect of not
retaining x. In ARC mode, __block id x; defaults to retaining x (just
like all other values). To get the manual reference counting mode
behavior under ARC, you could use __unsafe_unretained __block id x;.
As the name __unsafe_unretained implies, however, having a
non-retained variable is dangerous (because it can dangle) and is
therefore discouraged. Two better options are to either use __weak (if
you don’t need to support iOS 4 or OS X v10.6), or set the __block
value to nil to break the retain cycle.
Okay, so what's different about __block variable?
Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…]; //Why use __block. my controller is not changed at all
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil; //Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
};
Also why myController is not set to nil by compiler. Why do we have to do so? It seems that the compiler sort of know when myController will no longer be used again namely when the block expire.
When you have code of this form:
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
};
object will retain or copy the block you give to it. But the block itself will also retain object because it is strongly referenced from within the block. This is a retain cycle. Even after the block has finished executing, the reference cycle still exists and neither the object nor the block can be deallocated. Remember that a block can be called multiple times, so it cannot just forget all the variables it references after it has finished executing once.
To break this cycle, you can define object to be a __block variable, which allows you to change its value from inside the block, e.g. changing it to nil to break the cycle:
__block id object = ...;
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
object = nil;
// At this point, the block no longer retains object, so the cycle is broken
};
When we assign object to nil at the end of the block, the block will no longer retain object and the retain cycle is broken. This allows both objects to be deallocated.
One concrete example of this is with with NSOperation's completionBlock property. If you use the completionBlock to access an operation's result, you need to break the retain cycle that is created:
__block NSOperation *op = [self operationForProcessingSomeData];
op.completionBlock = ^{
// since we strongly reference op here, a retain cycle is created
[self operationFinishedWithData:op.processedData];
// break the retain cycle!
op = nil;
}
As the documentation describes, there are a number of other techniques you can also use to break these retain cycles. For example, you will need to use a different technique in non-ARC code than you would in ARC code.
I prefer this solution
typeof(self) __weak weakSelf = self;
self.rotationBlock = ^{
typeof (weakSelf) __strong self = weakSelf;
[self yourCodeThatReferenceSelf];
};
What happens is that the block will capture self as a weak reference and there will be no retain cycle. self inside the block is then redefined as __strong self = weakSelf before your code runs. This prevents self from being released while your block runs.

Using a block object instead of a selector?

I have:
[self schedule:#selector(tickhealth)];
And tickHealth method only has one line of code:
-(void)tickHealth
{
[hm decreaseBars:0.5];
}
is it possible to use block objects in place of a selector. for example something like:
[self schedule:^{
[hm decreaseBars:0.5];
}];
As Caleb & bbum correctly pointed out you cannot simply pass a block to your existing (and unchanged) - (void)schedule:(SEL)selector; method.
You can however do this:
Define block type:
typedef void(^ScheduleBlock)();
Change schedule: method to be defined similar to this:
- (void)schedule:(ScheduleBlock)block {
//blocks get created on the stack, thus we need to declare ownership explicitly:
ScheduleBlock myBlock = [[block copy] autorelease];
//...
myBlock();
}
Then call it like this:
[self schedule:^{
[hm decreaseBars:0.5];
}];
Further Objective-C block goodness compiled by Mike Ash that will get you kickstarted with blocks:
http://mikeash.com/pyblog/friday-qa-2008-12-26.html
http://mikeash.com/pyblog//friday-qa-2009-08-14-practical-blocks.html
http://mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html
You can't just pass a block in place of a selector because those two things have different types. However, if you have control over the -schedule: method, you can easily modify it to accept and use a block in place of a selector.

How can code inside an Objective-C block reference the block object itself?

self is merely a captured variable inside a block and doesn't reference the block itself, so how does a block reference itself without having an explicit captured variable for that purpose?
__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
strawberryFields);
you use the __block because the block will make a copy of the value of strawberryFields when the block is created which will be before the assignment.
you also must copy the block prior to any other copy operation or else you'll end up with a block that references the on-stack original version.
note that the above code leaks the block. Somewhere, there needs to be a release of that block to balance the copy.
I found this pattern to work and stable for ARC (automatic reference counting), both in Debug and Release builds.
-(void) someMethod
{
// declare a __block variable to use inside the block itself for its recursive phase.
void __block (^myBlock_recurse)();
// define the block
void (^myBlock)() = ^{
// ... do stuff ...
myBlock_recurse(); // looks like calling another block, but not really.
};
// kickstart the block
myBlock_recurse = myBlock; // initialize the alias
myBlock(); // starts the block
}
Initially I tried just putting a __block modifier to myBlock and use that variable directly to recurse within the block's implementation. That works on the ARC Debug build but breaks with an EXC_BAD_ACCESS on the Release build. On the other hand removing the __block modifier raises a "variable not defined when captured by block" warning (and I was reluctant to run it and test).
I have never tried this before and not 100% sure it's useful, if valid, but for example:
typedef void (^BasicBlock)(void);
__block BasicBlock testBlock;
testBlock = ^{NSLog(#"Testing %p", &testBlock);};
testBlock();
You probably have declare the variable with __block to prevent self-retain cycle.
The block needs some way to nil out its own reference. Typically it is done by storing the block in a property of the class.
Sometimes you can prefer to not use a property. Here is how you do it without a property:
__weak id weakSelf = self;
__block id block = ^{
if(weakSelf) {
// .. do whatever
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
else {
block = nil;
}
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
The key thing to keep in mind is that all code paths must lead to a block = nil. We do that here by calling the block every 5 seconds until weakSelf turns nil.
Note that in ARC, it's a little different -- __block object pointer variables are by default retained in ARC, unlike in MRC. Thus, it will cause a retain cycle. It is necessary for the block to capture a weak reference to itself (using __weak) in order to not have a retain cycle.
However, we still need a strong reference to the block somewhere. If there are no strong references, the block (which is on the heap since it's copied) will be deallocated. Thus, we need two variables, one strong and one weak, and inside the block use the weak one to reference itself:
__block __weak void(^weakBlock)();
void(^myBlock)();
weakBlock = myBlock = [^{ weakBlock(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
myBlock);