Reputation: 3970
I recently learned this trick for when I have to reference self within a block.
__weak MyObject *safeSelf = self;
[self doWithCompletionBlock:^{
HMFInventoryBatchItemsController *strongSelf = safeSelf;
if (strongSelf) {
[strongSelf doSomethingElse];
}
}];
But I've been wondering, what if I have a block within a block? Do I need to do the same thing again?
__weak MyObject *safeSelf = self;
[self doWithCompletionBlock:^{
HMFInventoryBatchItemsController *strongSelf = safeSelf;
if (strongSelf) {
__weak MyObject *saferSelf = strongSelf;
[strongSelf doAnotherThingWithCompletionBlock:^{
HMFInventoryBatchItemsController *strongerSelf = saferSelf;
if (strongerSelf) {
[strongerSelf doSomethingElse];
}
}];
}
}];
Or is this fine
__weak MyObject *safeSelf = self;
[self doWithCompletionBlock:^{
HMFInventoryBatchItemsController *strongSelf = safeSelf;
if (strongSelf) {
[strongSelf doAnotherThingWithCompletionBlock:^{
[strongSelf doSomethingElse];
}];
}
}];
Upvotes: 0
Views: 169
Reputation: 3400
__block MyObject *safeSelf = self;
[self doWithCompletionBlock:^{
[safeSelf doAnotherThingWithCompletionBlock:^{
[safeSelf doSomethingElse];
}];
}];
Hope it will do what it should normally does. Tell the compiler not to retain the __weak MyObject* no matter in which block scope it is. The fact is i didn't tested. Meanwhile I'll be surprised if it will actually retain MyObject *
Upvotes: 0
Reputation: 431
The good answer is, it depends. It's in general unsafe to do:
__weak MyObject *safeSelf = self;
[self doWithCompletionBlock:^{
[safeSelf doAnotherThingWithCompletionBlock:^{
[safeSelf doSomethingElse];
}];
}];
The reason for that, is that when you call -doAnotherThingWithCompletionBlock
if that method thinks it holds a reference on self
, which a selector usually assumes, and it dereferences self to access ivars, then you will crash, because you actually don't hold a reference.
So whether you need to take a new weak reference or not depends on the lifetime semantics you need/want.
EDIT:
By the way, clang even has a warning about that issue that you can enable in Xcode with the CLANG_WARN_OBJC_RECEIVER_WEAK
setting (CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK
is also useful while we're at it)
Upvotes: 2