Zhen
Zhen

Reputation: 12431

Objective C: Memory management in Block cases

I am wondering if I am using blocks as shown in the code below

__block Loader *loader = [[Loader alloc]initWithResourcePath:self.resourcePath]; 

[loader setCompletionHandler:^(NSArray *anArray){
    self.answerArray=anArray;
    [self reloadData];

}];

[loader getObjects];

My question is with regards to memory management. The analyzer tells me that there is a potential leak (since I did an alloc/init for my loader). How can I stop the leak here? I tried to release the loader at the end but that causes my app to stop functioning. Any advise is appreciated here

Upvotes: 1

Views: 426

Answers (3)

bbum
bbum

Reputation: 162712

Several issues:

  • there is no reason for loader to be declared __block; you aren't re-assigning in the block and, thus, the __block is pointless.

  • the leak is because you alloc/init the loader, but never release it

  • do not name methods getSomething; the get prefix is reserved for methods that return stuff by reference. Just call it objects. If it is supposed to trigger the load, then call it load or performLoad.

If it is asynchronous, then getObjects is pointless. If synchronous, then the completion block is pointless.

If loader is to be used synchronously, release it at the end of the method. If it is asynchronous, then the completion block could release it. Note that the use of __block in this case is still pointless; while referring to loader in the completion block will create a retain cycle, it will be broken when you explicitly Block_release() the block in your loader (because you must have done a Block_copy() when setting the completion handler if it is to be used asynchronously in the first place).

Upvotes: 3

Robert E. Menteer II
Robert E. Menteer II

Reputation: 49

I'm going to make some assumptions: 1) The completion handler (block) is used by method getObjects. 2) getObjects is asynchronous (it returns to the caller right away though it continues to process).

With these assumptions you can't send release after sending getObjects because getObjects is still using the completion handler.

Try sending a release or autorelease at the end of the completion handler. That should free loader provided reloadData is not also asynchronous.

Upvotes: 1

sergio
sergio

Reputation: 69027

If you plan to use loader outside of the function calling your block, it is highly possible that you need to store it in a ivar of your controller (I guess, it is a controller, but I don't know what kind of class owns the code you shows). Once you do that, you can release it in your dealloc.

The reasoning is that loader should live across several methods and runloop cycles, so a local variable will not do.

Otherwise, just release it at the end of the block, once you have done with it.

If this does not seem right to you, then possibly more code is needed.

Upvotes: 1

Related Questions