Recursive block gets deallocated too early - ios

I have written a recursive block following these guidelines:
NSMutableArray *groups = [NSMutableArray arrayWithArray:#[#"group1", #"group2", #"group3", #"group4"];
__block CommunicationCompletionHandler completion = [^{
[groups removeObjectAtIndex:0];
if ([groups count] > 0) {
// This will send some information to the network, and calls the completion handler when it receives a response
[mySocket saveGroup:groups[0] completion:completion];
}
} copy]; // Removing copy here doesn't work either
[mySocket saveGroup:groups[0] completion:completion];
In the saveGroup:completion: method, I add the completion handler to an array:
self.completionHandlers[SaveGroupCompletionHandlerKey] = [completion copy];
And when I receive a response, I call the following method (key is in this case SaveGroupCompletionHandlerKey):
- (void)performCompletionHandlerForKey:(NSString *)key {
if (self.completionHandlers[key]) {
((CommunicationCompletionHandler)self.completionHandlers[key])();
[self.completionHandlers removeObjectForKey:key];
}
}
The problem is that the completion handler only gets called once. The removeObjectForKey: line makes the block deallocate. If I uncomment that line, everything works fine. I'm not sure how the array has the last reference to this block, since I add a copy (which I believe is being optimized to a retain).
For clarity, the flow of the app is:
Send data for first group over network
Receive response
Call completion handler
In the completion handler, send data for next group (this is the recursive part).
Anybody here who can point out what I'm doing wrong?

In -performCompletionHandlerForKey: you remove the completion handler from your dictionary after executing the block, which means that the handler will always be removed from the dictionary after one run.
Instead, store the block in a temporary variable and remove it from the dictionary before executing the block.
By the way, the advice to remove the weak reference is wrong. As your code is written now, your block will never be deallocated. The typical block recursion pattern is this:
__weak __block MyBlock weakHandler;
MyBlock handler = ^ {
if (foo) {
MyBlock strongHandler = weakHandler;
[bar asyncOperationWithCompletion:strongHandler];
}
};
weakHandler = handler;
[bar asyncOperationWithCompletion:handler];

A popular way to avoid retain retain cycles is to create a weak reference to the object before defining the block, then create a strong reference inside the block and set it to that weak reference. This method is frequently used to avoid strongly capturing self inside of blocks:
- (void)someMethod {
__weak MyType *weakSelf = self;
[self someMethodWithABlockArg:^{
MyType *strongSelf = weakSelf;
[strongSelf someOtherMethod];
}];
}
The strong reference created inside the block prevents the object from being deallocated while the block is running. You can, of course, do the same with any object type.
Edit2: Looks like [someBlock copy] is indeed fine. Have you tried running Analyze on the code? It may be that completion is not yet initialized when it is referred to inside of the block.

Related

objective c - block retain cycle

I have a block retain cycle question,
suppose I have the following 3 methods, all in one class.
- (void)foo1WithBlock:(void (^)(BOOL success))completion
// do something...
completion(YES)
}
- (void)foo2 {
// do something...
}
- (void)foo3 {
[self foo1WithBlock:^(BOOL success) {
[self foo2];
}];
}
Will foo3 create a retain cycle?
No, there is no retain cycle.
However, self will be captured. This means, self will be imported into the lexical scope of the compound statement (the statements executed by the block). This involves making a copy of the "outside" variable self which creates the block's variable self.
A block can be copied and released. A block_copy operation will "move" the captured variables onto the heap. They exists there until the block gets destroyed via block_release operation. The compiler/runtime provides internal functions to copy and release a block and performs them when required. For example, if the block is executed asynchronously via dispatch_async() the block will have to be copied first, and later when the block is finished, released again. These block_copy and block_release operations are inserted by the compiler and executed by the runtime, so don't worry.
If the block will be copied, as an effect self will be retained, and released again when the block gets released - which happens when the block has been finished.
In effect, this guarantees that self within the block and during the life-time of the block is valid (that is, it won't get deallocated), whether it is called synchronously or asynchronously. When the block has been executed asynchronously, the block has been copied, and thus self has been retained. And self will be only released again until after the block finishes. This also means, that the block "will" extend the life time of self until after the block finishes.
No, there will no retain cycle..as you are not calling each other method here.
- (void)foo3 {
[self foo1WithBlock:^(BOOL success) {
[self foo2];
}];
}
In this case, if you don't understand the lifetime of the block you are passing to foo1WithBlock: it is probably a good idea to use this idiom to prevent a the block from inappropriately extending the lifetime of self.
- (void)foo3 {
__weak ParentType *wself = self; //create a weak reference (weak automatically gets set to nil on dealloc)
[self foo1WithBlock:^(BOOL success) {
ParentType *self = wself; //create a local strong reference for the life of the block.
[self foo2];
}];
}
if you are using cocoapods libextobjc has a EXTScope which provides helper macros for this:
- (void)foo3 {
#weakify(self);
[self foo1WithBlock:^(BOOL success) {
#strongify(self);
[self foo2];
}];
}

where to release a __block variable?

I have following code snippet:
-(void) doSomething
{
__block NSMutableArray *objArray = [[NSMutableArray alloc] initWithCapacity:0];
[self performOperationWithBlock:^(void)
{
//adding objects to objArray
.
.
//operation with objArray finished
// 1. should objArray be released here?
}];
//2. should objArray be released here?
}
Should I autorelease the objArray?
If it's an asynchronous call, it would make sense to create the NSMutableArray inside the actual block:
[self performOperationWithBlock:^(void)
{
NSMutableArray *objArray = [[NSMutableArray alloc] initWithCapacity:0];
//adding objects to objArray
.
.
//operation with objArray finished
// 1. should objArray be released here?
}];
As you won't be needing it after the block (it only makes sense for the duration of the async operation), so in the end release it after you have used it. Or, you can simply:
NSMutableArray *objArray = [NSMutableArray array];
And in this case you don't need to release it.
If it's a sync call, you should release it after the block.
Note: I am assuming you are populating the NSMutableArray before being used on the block, which means it makes sense to be created before the block starts.
Async approach:
-(void) doSomething
{
// Remove the `__block` qualifier, you want the block to `retain` it so it
// can live after the `doSomething` method is destroyed
NSMutableArray *objArray = // created with something useful
[self performOperationWithBlock:^(void)
{
// You do something with the objArray, like adding new stuff to it (you are modyfing it).
// Since you have the __block qualifier (in non-ARC it has a different meaning, than in ARC)
// Finally, you need to be a good citizen and release it.
}];
// By the the time reaches this point, the block might haven been, or not executed (it's an async call).
// With this in mind, you cannot just release the array. So you release it inside the block
// when the work is done
}
Sync Approach:
It assumes that you need the result immediately, and it makes sense when you do further work with the Array, after the block has been executed, so:
-(void) doSomething
{
// Keep `__block` keyword, you don't want the block to `retain` as you
// will release it after
__block NSMutableArray *objArray = // created with something useful
[self performOperationWithBlock:^(void)
{
// You do something with the objArray, like adding new stuff to it (you are modyfing it).
}];
// Since it's a sync call, when you reach this point, the block has been executed and you are sure
// that at least you won't be doing anything else inside the block with Array, so it's safe to release it
// Do something else with the array
// Finally release it:
[objArray release];
}
You should release it after the performOperationWithBlock: method has finished, in my opinion, provided that method is synchronous (i.e. works on the same thread as the calling thread).
If that method is asynchronous then it should be released within the block.
If you're not using ARC, you should release the array when you no longer need it. According to the comments you added and assuming the doSomething method doesn't do anything with the array outside of the block, it should be at your 1. mark.
Option 2. Release it after [self performOperationWithBlock:...]. Block will retain and release yours objArray by himself. Releasing inside block is dangerous: block can be performed twice and then objArray will be released twice, but it's should de released once. So there is only one option left: 2.

A strange block issue in Objective-C

I have a AuthService class that has a method to perform asynchronous connection to login. This class has implemented NSURLConnectionDataDelegate protocol so that when the server responses, it calls the completion handler previously set by a View Controller to update UI.
This is the definition of that completion handler
#property void (^completionHandler)(LoginResult *result);
This is when the class receives server response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString *response = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
//Do something with the response and create an instance of LoginResult class
self.completionHandler(loginResult);
}
If the completion handler block merely just calls NSLog to write to console the information of the login result which is passed as argument, then it runs perfectly with no error. But when I want to call methods of the ViewController that owns the block, something strange just happens.
I know that there is a retain cycle when you include an object in a block which owns that block. So this is the way how I code it.
__block typeof(self) bself = self;
[authService login:blablabla completionHandler:^(LoginResult *result) {
[bself didReceiveLoginResult:result];
}
I assumed this will prevent from running into a retain cycle. But I got "Thread: EXC_BAD_ACESS" error when debugging.
P.S.
Following codes for example run perfectly even if that property is not declared as "copy"
[authService login:blablabla completionHandler:^(LoginResult *result) {
NSLog(#"Login %#", result.success ? #"success" : #"failed");
}
The property should be declared as copy otherwise the block will stay on stack and can be already deallocated when you call it.
Also, there are simple ways how to prevent a retain circle. Just release the block when you have used it, e.g.
self.completionHandler(loginResult);
self.completionHandler = nil;
No clever magic with __block is neccessary. Retain cycles are allowed when they are temporary.
Edit:
If there is no reference to self in the block, the compiler will make it a global block and it won't ever get deallocated. See http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
Blocks need to be copied if you want to use them outside of the current function, so you will need to copy it before storing it in your property:
- (void)setCompletionHandler:(void (^)(LoginResult *))handler {
_completionHandler = [handler copy];
}
Then when you assign the completion handler in your login:completionHandler: method, it will be copied before being stored in the instance variable.
In this way, the block you pass to the function will be copied before being stored in the property, and the copy will be located on the heap, not the stack, so it'll still exist when you run it later.

Block in block, with __weak self

I'm trying to figure out if I do this right:
If I have one block, I'll do this:
__weak MyClass *weakSelf = self;
[self performBlock:^{ //<< Should I use self, or weakSelf here?
[weakSelf doSomething];
} afterDelay:delay];
But what happens if there's a block in a block? Would this be correct?
__weak MyClass *weakSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also, in the function below, do I need to use [block copy]?
- (void)performBlock:(void (^)(void))block afterDelay:(float)delay
{
if (block)
{
if (delay > 0)
{
[self performSelector:#selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay];
}
else
{
[self executeBlockAfterDelay:[block copy]];
}
}
}
- (void)executeBlockAfterDelay:(void(^)(void))block
{
if (block)
block();
}
In this case (below) use just strong self, because the block is copied just for those few seconds. And usually if you want the self to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.
[self performBlock:^{
[self doSomething]; // strong is OK
} afterDelay:delay];
Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.
Example:
self.callback = ^{
[self doSomething]; // should use weakSelf
};
This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:
self.callback(); //invoke
self.callback = nil; //release
When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:
[self performSelector:#selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];
Rather than implementing -performBlock:afterDelay:, just use dipatch_after(). Among other things, that's not a message delivered to an object, so there's no question of what receiver to target it at.
Actually, there's no memory management issue here at all. One typically only needs to do a "weak self" approach when an object retains a block and the block (perhaps implicitly) retains that same object. However, the object is not retaining the block. It is being retained by the framework until the -performSelector:withObject:afterDelay: fires, but that's not a retain cycle.
If there were a retain cycle, then you should not reference self in the blocks. So, your nested case is wrong in invoking a message on self rather than weakSelf.
Finally, yes, you do need [block copy] whenever you are keeping a block after execution leaves the scope of its declaration or if you pass it to non-block-specific API that does. That is, you don't need to copy a block when you pass it to, say, dispatch_async() because that's a block-aware API that knows to make its own copy as necessary. But -performSelector:withObject:afterDelay: is not block-aware. It just treats its argument as a generic object and retains it. So, you do have to copy the block when passing it to that.
One the most important thing to understand about blocks is that they capture a piece of code (including values) in an abstract entity that can be manipulated as an atomic object (keep it somewhere, pass it, copy, etc...). Actually it is implemented in a way that guarantee that by default your block will remain valid and executable safely later.
Then capturing and retaining the required dependencies inside the block is necessary.
Unfortunately, in some cases (quite often actually) the block is retained by the instance that creates it and it retains itself that instance. This is called a retain loop and makes your object and your block impossible to dealloc unless you break one of the retaining relation yourself. This can happen if you reference your block with an instance variable for example and you don't nillify it manually.
This is probably the main issue with blocks especially because sometime, you don't know that your block retains your self instance (NSAssert within your block for example). Then:
If you execute your block immediately and release it (use your block
with dispatch release it after execution) there is no risk since you
are sure your object referenced by self still exist.
But if the execution is delayed it is important to retain your object within your block. But in that case your object should not retain your block to avoid a retain loop (A retains B and B retains A). If you define and optionally reference your block in the private scope of method it is perfect.
About copy. Yes it can be safer to use copy if your block in passed as a method argument to be sure you have a clean exclusive block in this scope with a +1 retainCount. But maybe ARC already do it for you. Not sure about that. For example it performWithSelector seems to do it for free, then copy is not dangerous. Just a useless. Sometime the compiler can optimise that by removing it but it has to be checked.
I usually do this:
__unsafe_unretained __block id blockSelf = self;
and then use it in my blocks no issues.
So in your case:
__unsafe_unretained __block MyClass *blockSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also to make your life a tad easier - make a utilities class and put this in the header
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block);
and then this in the .m file
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block)
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
Import the utilities into your prefix and you can go:
__unsafe_unretained __block MyClass *blockSelf = self;
RunAfterDelay(1.0f,^{
[blockSelf doSomething];
RunAfterDelay(delay,^{
[blockSelf doSomething];
})
});
I find it a bit nicer to read than the verbose default ones.
Hope this helps :)

Memory management with blocks when class object is released

Assuming an example block as shown below executed.
[testBlock testPerformWithBlock:^(BOOL finished) {
if (finished) {
self.textField.text = #"Finished";
NSLog(#"Edited to add an textfield update inside block");
}
}];
What will happen if I pop the view controller that contains the object testBlock before the block returns the value of BOOL. Will the objects get deallocated properly?
Everything inside a block is retained until the block is released from memory. If the object testBlock is still executing testPerformWithBlock and the block is still alive, then everything inside the block is retained.
You are only doing an NSLog in there, so nothing will change.
However, if you do this:
if (finished) {
[self doSomething];
}
self is being used, and it will be retained, so take some caution if you are storing the blocks in some ivar somewhere
I don't understand what you are asking. There is no problem with memory management in your example. If you did not explicitly retain something, you do not need to explicitly release it.
You will get warning that strongly capturing self inside block will lead to retain cycle it will not crash but its not proper you need to do as they say strong weak dance.You can do this.
__weak typeof(self)ref=self;
^(<your bock>){
__strong typeof(ref)strongSelf=ref;
if(strongSelf)//or if(!strongSelf)return;
{
[strongSelf-><variable> methodCall];
}
};
There will be no deallocated error.
Though the retainCount of "testBlock" will not change after the invocation, the block will not be released before it runs to the end.
The result is that program will run perfectly no matters "testBlock" dealloc or not.
The sample codes following:
- (void)lazyFetchingImage:(void (^)(void))finishBlock {
[[NSOperationQueue mainQueue] addOperationWithBlock:finishBlock];
}
MainVCAppDelegate *dd = [MainVCAppDelegate new];
NSLog(#"count==%i",[dd retainCount]);
[dd lazyFetchingImage:^{
NSLog(#"22");
}];
NSLog(#"count==%i",[dd retainCount]);
[dd release];
The out put should be :
count==1
count==1
22

Resources