Mario
Mario

Reputation: 2451

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?

Upvotes: 3

Views: 2309

Answers (3)

Jon
Jon

Reputation: 462

- (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];
   }]; 
}

Upvotes: -1

CouchDeveloper
CouchDeveloper

Reputation: 19098

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.

Upvotes: 9

Samkit Jain
Samkit Jain

Reputation: 2523

No, there will no retain cycle..as you are not calling each other method here.

Upvotes: 0

Related Questions