Reputation: 2451
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
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
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
Reputation: 2523
No, there will no retain cycle..as you are not calling each other method here.
Upvotes: 0