Reputation: 1290
What's the correct way to reference 'self' (and ivars) within blocks without the block creating a strong reference (and thus incrementing the ref count)?
For instance, I've found the following increments the ref count for 'self':
^(id sender) {
[self.navigationController popViewControllerAnimated:YES];
}
In order to circumvent the above, I've been doing the following:
__weak WhateverController *weakSelf = self;
^(id sender) {
[weakSelf.navigationController popViewControllerAnimated:YES];
};
And yes, I realize this is pseudocode.
Upvotes: 3
Views: 1008
Reputation: 28339
Also, an indirect reference to self also creates a retain on self. For example, if _ivar
were an instance variable, accessing it is an implicit reference to self so the following would also retain self.
^(id sender) {
[_ivar popViewControllerAnimated:YES];
}
Furthermore, to expand on your weak
example, it is OK to send a message to a weak reference. If it's nil, nothing will happen. If not, then the compiler will generate code that ensures the reference remains valid through the invocation of the method.
So, this is fine:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
}
because foo will either be nil
or if not, it is guaranteed to remain non-nil throughout the execution of doSomething
.
However, the following would be inadvisable because self
could go to nil
in-between calls, which is probably not what you want:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
[weakSelf.foo doSomethingElse];
}
In that case, you probably want to create your own strong reference inside the block, so you have a consistent value throughout the execution of the block.
On the other hand, if you access iVars directly through a weak reference, you must do the weak-strong dance because this code:
__weak Foo *weakSelf = self;
^(id sender) {
weakSelf->_foo = bar;
}
will blow up if weakSelf
is nil
.
Thus, in the last two situations above, you want to do something like:
__weak Foo *weakSelf = self;
^(id sender) {
Foo *strongSelf = weakSelf;
if (!strongSelf) return;
// Now, do anything with strongSelf, as it is guaranteed to be around
}
Of course, the iVar situation is only a problem if you actually access iVars directly...
Upvotes: 10
Reputation: 4003
Apple's notation is sself but other than that - you're fine.
In a non arc project use the following code to prevent 'self' from being retained by the block:
__block id sself = self
Upvotes: 2