Retain cycle warning on __block variable that is an ivar - ios

I'm subclassing AVQueuePlayer, and in my constructor, where I pass the AVPlayerItem's it needs to play, I want to add an observer on the first item to play.
So I'm using the AVPlayer method addBoundaryTimeObserverForTimes:queue:usingBlock:. Proper implementation requires me to call removeTimeObserver: on the "opaque" object that addBoundary method returns.
In order to retain the object for however long is necessary, I declared it as a __block ivar:
#property (nonatomic, copy) __block id obs;
then in my own init method I have:
__block AVPlayer* blockPlayer = self;
_obs = [self addBoundaryTimeObserverForTimes: times
queue:NULL
usingBlock:^{
// Post a notification that I can then act on
[[NSNotificationCenter defaultCenter]
postNotificationName:#"PlaybackStartedNotification"
object:nil];
// Remove the boundary time observer
[blockPlayer removeTimeObserver:_obs]; // Warning here
}];
There's a lot going on here... And although the specific warning comes when I try to remove the time observer, I'm also posting a notification, which I may also change to pass a variable in the object: part. I'm also setting self as the observer...
I've read a lot of other answers on potential solutions (example)
but I haven't really found anything about using block variables.
Is my code unsafe or am I okay?
Edit: I originally mistyped the name of the #property as __block id observer when I indeed meant for it to be __block id obs. The accepted answer thus answered both scenarios! (Awesome!)

(All code typed directly into answer, treat it as pseudo-code and expect there to be minor typos at least!)
You are unfortunately misunderstanding the purpose and behaviour of __block - it is an attribute which only applies to local variables and modifies their lifetime so they can be safely updated by a block. So:
In order to retain the object for however long is necessary, I declared it as a __block ivar:
#property (nonatomic, copy) __block id observer;
is an invalid property declaration, as properties are instance methods usually backed by instance - not local - variables. The current Apple compiler unfortunately just ignores the meaningless __block rather than reporting an error - a bug which has previously caused confusion for SO inquirers (you should submit a bug report to Apple to encourage them to fix it).
Next you write:
__block AVPlayer* blockPlayer = self;
so you can use blockPlayer within your block instead of self in an attempt to avoid a retain cycle. This does not work, indeed it simple adds another (anonymous) object into the cycle... What you need here is a weak reference:
__weak AVPlayer *blockPlayer = self;
Weak references break a cycle, but within the block you must first create a strong reference from them and check it is not NULL - which it will be if the object it weakly references has been destroyed. The code to do this within your block will be something like:
// Remove the boundary time observer if blockPlayer still exists
AVPlayer *strongBlockPlayer = blockPlayer; // obtain strong reference from weak one
if (strongBlockPlayer)
[strongBlockPlayer ...];
Even after these changes you have a bigger problem. In your code you have:
_obs = [self addBoundaryTimeObserverForTimes:times
queue:NULL
usingBlock:^{
...
[blockPlayer removeTimeObserver:_obs];
}];
Here you are attempting to use the value of _obs within your block.
At this point your question becomes unclear, is _obs meant to be a local variable or the property observer? We'll consider both cases:
Local Variable
If _obs is a local variable your code will not work. When a block is created the values of any local variables used by the block are copied into the block itself, so here the value of _obs would be copied. However _obs will not have a valid value at this point, that will only happen after the call to addBoundaryTimeObserverForTimes:queue:usingBlock: returns and the assignment of its return value, which is after the block has been created and passed to the same call...
This problem is similar to defining a local recursive block and has the same solution. If a local variable is declared with the __block attribute, so that its lifetime is modified to match that of any blocks using it and thus those blocks can modify its value, then the value in the local variable is not copied into the block - instead the block gets a reference to the variable which it uses to read/write the variable as needed.
So to make the code work you change it to:
__block id obs = [self addBoundaryTimeObserverForTimes:times
queue:NULL
usingBlock:^{
...
[blockPlayer removeTimeObserver:obs];
}];
In this version:
The local variable obs will be created in such a way that its lifetime is at least as long as your block (we'll skip the details of how the compiler arranges this - they are interesting but not of critical importance);
The block is created with a reference to the variable jobs;
The method addBoundaryTimeObserverForTimes:queue:usingBlock: is called passing it the block;
The method returns and its result is assigned to obs; and
(A little later) the block is invoked, reads obs, and obtains the value stored there after the method call.
Property Reference
If you've made a typo and you intended _obs to be the property observer then the LHS of the assignment should be self.observer and the RHS should be blockPlayer.observer, which allowing for the need for the weak reference would be:
__weak AVPlayer *blockPlayer = self;
self.observer = [self addBoundaryTimeObserverForTimes:times
queue:NULL
usingBlock:^{
...
// Remove the boundary time observer if blockPlayer still exists
AVPlayer *strongBlockPlayer = blockPlayer; // obtain strong reference from weak one
if (strongBlockPlayer)
[strongBlockPlayer removeTimeObserver:strongBlockPlayer.observer];
}];
This will work as by the time the block is called and reads strongBlockPlayer.observer the call to addBoundaryTimeObserverForTimes:queue:usingBlock: block will have returned and the assignment to the property made.
Local Variable vs. Property for obs/observer?
Which of the above two versions, both of which should work, is better? Probably the local variable version as (a) you don't appear to need the property elsewhere and (b) it localises the need for the variable to just the statement, the method call, which needs it, which in turn helps readability and debugging. However that is an opinion and some might disagree - make your own choice!
HTH

Related

Do I need to use use Strongify and Weakify in blocks if the variable calling it is local [duplicate]

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.

Do I need to use a weak self pointer if a method called from a Block uses self?

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.

Using self and self properties inside a block in non-arc environment

I have been using blocks and familiar with the memory management when using self inside blocks in
Non-ARC environment
But I have two specific questions:
1) I understand I can use __block to avoid the retain cycle a retained block which in turn using self can create, like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
blockSelf.someProperty = abc;
[blockSelf someMethod];
};
This will avoid the retain cycle for sure but I by doing this I have created a scope for self to be released and eventually deallocated by someone else. So when this happen self is gone and blockSelf is pointing to a garbage value. There can be conditions when the block is executed after the self is deallocated, then the block will crash as it is trying to use deallocated instance. How do we can avoid this condition? How do I check if blockSelf is valid when block executes or stop block from executing when self is deallocated.
2) On the similar lines suppose I use block like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
[blockSelf someMethod:blockSelf.someProperty];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
Now there can be situations where self is not released but someProperty is released before someMethod's execution starts (This could happen when there are multiple threads). Even if I do self.someProperty = nil; when it is release, myClassProperty is not nil and pointing to some garbage, hence when someMethod is executed the first line will lead to crash. How do I avoid this?
This is the same issue as non-zeroing weak references everywhere else in non-ARC code, e.g. delegates etc. (MRC doesn't have zeroing weak references; so these are the only kind of weak reference in MRC. Yet people were still able to write safe code in the pre-ARC days.)
Basically, the solution is that you need a clear map of ownership. Either self is responsible for keeping the block alive; or some other object is responsible for keeping the block alive.
For example, with delegates, usually, a "parent" object is the delegate of a "child" object; in this case the "parent" object is responsible for keeping the "child" object alive, so the "parent" object will outlive the "child" object, thus the back reference can be weak and is safe (because the child object's methods could only possibly be called by the parent object while the parent object is alive).
On the other hand, if you have an asynchronous operation, and the block is given to the operation as a callback, then usually the operation is responsible for holding onto the block. In this case, self would not hold onto the block. And the block would hold a strong reference to self, so that when the operation is done, it can still safely do whatever it is that it needs to do on self. In fact, whatever object self is, it doesn't even need to be retained by whoever uses it, since it is indirectly retained by the asynchronous operation -- it can just be a create, fire, and forget kind of thing.
If you have something where the block is sometimes kept alive by self, and sometimes kept alive by something else, then you should re-think your design. You say "There can be conditions when the block is executed after the self is deallocated"; well, you should describe your whole design and how this can happen. Because usually, for something that is executed asynchronously, self need not hold onto the block.
Your code is really confusing and doesn't make sense. For example, why would you assign to a parameter (myClassProperty)? What's the point of passing an argument when the parameter is going to be overwritten anyway? Why would you name a local variable "myClassProperty"?
What I think you are asking about is accessing a property that can be changed on different threads, and how to deal with the memory management of that. (This question is unrelated to blocks or ARC/MRC. It is equally an issue in ARC.)
The answer is that you need an atomic property. You can make a synchronized property atomic, or implement an atomic property manually if you know how. What an atomic property of object pointer type needs to do is its getter needs to not just return the underlying variable, but also retain and autorelease it, and return the result of that. The retrieval and retaining in the getter occurs in a critical section that is synchronized with a critical section in the setter that includes the release of the old value and retaining of the new. Basically, this synchronization guarantees that the value will not be released in the setter in between retrieving the value and retaining it in the getter. And the value returned from the getter is retained and autoreleased, so it is guaranteed to be alive for the duration of the scope.
Solution for 2)
__block MyClass *blockSelf = self;
self.myBlock = ^{
datatype* p = [blockSelf.someProperty retain];
[blockSelf someMethod:p];
[p release];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
For 1) don't know how you use myBlock. If it's used only by self, then all will be fine. And if it's used by some other object, then it's also should have retained reference at self and then there is also all will be fine.

Memory issue when calling dispatch_async with local variable

I am having issues in code when calling dispatch_async. I think that issue is due to ARC reclaiming the object, before it is used in a block, as the method that dispatches it finishes.
- (void) method:(SomeClass *) someClass {
// local variable
NSNumber *someValue = someClass.somePropertyOnManagedObject;
dispatch_async(queue, ^() {
/* call some singleton object passing variable
* when access the variable, reference is nil
*/
[[DashboardFacade sharedInstance] someMethod:someValue];
});
}
After having looking through much documentation, I conclude
Block accesses no parameters – nothing to discuss
Block accesses simple type parameters e.g. BOOL, int - these are copied and not a problem
Block accesses parameter of method that dispatched it - I am not sure, but think
that this is ok
Block accesses property of self – as long as self “lives” until the call has finished ok
Block accesses local variable in method that dispatched it
If we use some semaphores such that we wait for the block to return before leaving the method, then all ok
Otherwise variable may have been garbage collected before block can use.
I think that the solution is to use __block modifier such that ARC retains the variable.
My question is
Is the above technically correct, e.g. using __block will resolve the problem and not introduce other problems?
Why can't I find this anywhere on the internet/google?
Is the above technically correct, e.g. using __block will resolve the
problem and not introduce other problems?
Yes it's technically correct, __block, on ARC, allows you to change the variable (in this case to where its pointing, since it's a NSNumber *), that was declared outside the block context.
Why can't I find this anywhere on the internet/google?
I think the problem is not related to this particular place of your code, but something else.
someValue inside the block can be nil only if it is nil after this assignment:
NSNumber *someValue = someClass.somePropertyOnManagedObject;
Blocks retain objects that are being captured by the blocks as a result of those variables being used inside the blocks. And it doesn’t matter if it is self or a local variable from the scope that is visible to the block.

Clarification on Apple's Block Docs?

I am working through some retain-cycle issues with blocks/ARC, and I am trying to get my head around the nuances. Any guidance is appreciated.
Apple's documentation on "Blocks and Variables" (http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html) says the following:
If you use a block within the implementation of a method, the rules
for memory management of object instance variables are more subtle:
If you access an instance variable by reference, self is retained; If
you access an instance variable by value, the variable is retained.
The following examples illustrate the two different situations:
dispatch_async(queue, ^{
// instanceVariable is used by reference, self is retained
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
// localVariable is used by value, localVariable is retained (not self)
doSomethingWithObject(localVariable);
});
I find this explanation confusing.
Is this appropriate use of the "by value" / "by reference" terminology? Assuming that these variables are of the same type (id), it seems like the distinguishing characteristic between them is their scope.
I do not see how self is being referenced in the "by reference" example? If an accessor method were being used, (e.g. - below), I could see self being retained.
doSomethingWithObject(self.instanceVariable);
Do you have any guidance on when one might want to do things one way or the other?
If conventional wisdom is to utilize the "by value" variables, it seems like this is going to result in a lot of additional code for additional variable declarations?
In a circumstance where nested blocks are coming into play, it seems like it may be more maintainable to avoid declaring the blocks inside of each other as one could ultimately end up with a potpourri of unintentionally retained objects?
Think of the case of using instanceVariable as an equivalent of writing self->instanceVariable. An instance variable is by definition "attached" to the self object and exists while the self object exists.
Using instanceVariable (or self->instanceVariable) means that you start from the address of self, and ask for an instance variable (that is offset of some bytes from the self object original address).
Using localVariable is a variable on its own, that does not rely on self and is not an address that is relative to another object.
As the blocks capture the variables when they are created, you typically prefer using instance variables when you mean "when the block is executed, I want to get the value of the instance variable at the time of the execution" as you will ask the self object for the value of the instance variable at that time (exactly the same way as you would call [self someIVarAccessorMethod]). But then be careful not to create some retain cycles.
On the other hand, if you use localVariable, the local variable (and not self) will be captured when the block is created, so even if the local variable changes after the block creation, the old value will be used inside the block.
// Imagine instanceVariable being an ivar of type NSString
// And property being a #property of type NSString too
instanceVariable = #"ivar-before";
self.property = #"prop-before";
NSString* localVariable = #"locvar-before";
// When creating the block, self will be retained both because the block uses instanceVariable and self.property
// And localVariable will be retained too as it is used directly
dispatch_block_t block = ^{
NSLog(#"instance variable = %#", instanceVariable);
NSLog(#"property = %#", self.property);
NSLog(#"local variable = %#", localVariable);
};
// Modify some values after the block creation but before execution
instanceVariable = #"ivar-after";
self.property = #"prop-after";
localVariable = #"locvar-after";
// Execute the block
block();
In that example the output will show that instanceVariable and self.property are accessed thru the self object, so self was retained but the value of instanceVariable and self.property are queried in the code of the block and they will return their value at the time of execution, respectively "ivar-after" and "prop-after". On the other hand, localVariable was retained at the time the block was created and its value was const-copied at that time, so the last NSLog will show "locvar-before".
self is retained when you use instance variables or properties or call methods on self itself in the code of the block. Local variables are retained when you use them directly in the code of the block.
Note: I suggest you watch the WWDC'11 and WWDC'12 videos that talks about the subject, they are really instructive.
Is this appropriate use of the "by value" / "by reference" terminology? It's at least analogous to the typical use. Copying a value to a local variable is like copying a value onto the stack; using an ivar is like passing a pointer to a value that's stored somewhere else.
I do not see how self is being referenced in the "by reference" example? When you use an instance variable inside a method, the reference to self is implied. Some people actually write self->foo instead of foo to access an ivar just to remind themselves that foo is an ivar. I don't recommend that, but the point is that foo and self->foo mean the same thing. If you access an ivar inside a block, self will be retained in order to ensure that the ivar is preserved for the duration of the block.
Do you have any guidance on when one might want to do things one way or the other? It's useful to think in terms of the pass by reference/pass by value distinction here. As AliSoftware explained local variables are preserved when the block is created, just as parameters passed by value are copied when a function is called. An ivar is accessed through self just as a parameter passed by reference is accessed through a pointer, so its value isn't determined until you actually use it.
it seems like this is going to result in a lot of additional code for additional variable declarations? Blocks have been a feature of the language for a while now, and I haven't noticed that this is a problem. More often, you want the opposite behavior: a variable declared locally that you can modify within a block (or several blocks). The __block storage type makes that possible.
it seems like it may be more maintainable to avoid declaring the blocks inside of each other as one could ultimately end up with a potpourri of unintentionally retained objects? There's nothing wrong with letting one or more blocks retain an object for as long as they need it -- the object will be released just as soon as the blocks that use it terminate. This fits perfectly with the usual Objective-c manual memory management philosophy, where every object worries only about balancing its own retains. A better reason to avoid several layers of nested blocks is that that sort of code may be more difficult to understand than it needs to be.

Resources