Why are __block variables not retained (In non-ARC environments)? - ios

I was reading through the documentation on __block variables, and thinking about the cases where I use __block. To me, it seems like I need it in two cases:
To mark a variable as read-write when used within a block
To avoid retain cycles when referencing self within a block
On the surface it doesn't seem like these two things are related. I consider the fact that __block variables not being retained as more of a trick I need to remember for the specific use case of avoiding retain cycles.
I'm wondering, is there a more important, architectural reason why they must not be retained? I would think some other keyword to indicate this might be more clear, as to not mix up the two features listed above.
update -
I should mention this is code that does not use ARC. I now see that __block variables are in fact retained in ARC.

__block variables are not retained if you use Manual Reference Counting. The reason can be found here: http://www.mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html:
A simple workaround to this lies in the fact that __block variables
are not retained. This is because such variables are mutable, and
automatic memory management of them would require each mutation to
generate memory management code behind the scenes. This was seen as
too intrusive and difficult to get right, especially since the same
block may be executing from multiple threads simultaneously.
and also here: http://lists.apple.com/archives/objc-language/2009/Dec/msg00100.html
There is no way to properly and efficiently manage the retain counts
upon re-assignment of the value within the variable.
(I could not find an "official" reference in the Apple documentation.)
As documented in the "Transitioning to ARC Release Notes", this behavior changed with ARC:
In manual reference counting mode, __block id x; has the effect of not
retaining x. In ARC mode, __block id x; defaults to retaining x (just
like all other values). To get the manual reference counting mode
behavior under ARC, you could use __unsafe_unretained __block id x;.
As the name __unsafe_unretained implies, however, having a
non-retained variable is dangerous (because it can dangle) and is
therefore discouraged. Two better options are to either use __weak (if
you don’t need to support iOS 4 or OS X v10.6), or set the __block
value to nil to break the retain cycle.

Related

Does object need (a) `__block` modifier or (b) weak reference, when accessed from within a block in Objective-C?

In Objective-C (as of Xcode 7), the __block modifier for use with primitives is clearly explained in Stack Overflow such as here and by Apple here in the Blocks Programming Guide. Without the label, a copy of the primitive is captured and the original cannot be modified from within the block. With the label, no copy, and the original can be modified from within the block.
But for use with pointers to objects, the situation is not so well explained. Here Apple says either “a strong reference is made to self” or “a strong reference is made to the variable”. But then at the end of the page Apple says:
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
What does “override this behavior” mean?
Further complicating things is that some posts on Stack Overflow talking about making a weak reference when calling an object from within a block.
I am not trying to establish an object. I just want to modify an existing object’s state from within a block. I believe the block is being called synchronously, within the same thread.
Imagine:
Clicker* myClicker = [[Clicker alloc] init] ;
…
// Declare a block.
void (^myBlock)( );
// Populate the block.
myBlock = ^ void ( ) {
[myClicker click] ; // Updating some state in that object, such as incrementing a counter number or adding an element to a collection.
};
// Call `myBlock` synchronously (same thread) from some other code.
… // … invokes `myBlock` repeatedly …
My questions:
How should that code be modified with __block modifier?
How should that code be modified with weak references?
What other issues apply to an object’s state modified from within a block?
First of all, the basic point of __block is the same for all types of variables (primitive variables, object-pointer variables, and all other variables) -- __block makes the variable shared between the outside scope and the scopes of the blocks that capture it, so that an assignment (=) to the variable in one scope is seen in all other scopes.
So if you don't use __block, if you assign to an object-pointer variable to point to another object outside the block after the block is created, the block won't see the assignment to the variable, and will still see it pointing to the object it was pointing to when the block was created. Conversely, inside the block you won't be able to assign to the variable. If you do use __block, then assignments to the variable to point to another object, either inside or outside the block, will be reflected in the other scopes.
Note that mutation of objects' state has nothing to do with assignment to variables. You mutate objects' state by calling a mutating method on a pointer to the object, or you can alter a field directly using a pointer to the object using the -> syntax. Neither of these involve assigning to a variable holding the pointer to the object. On the other hand, assigning to a variable holding a pointer to an object only makes the pointer point to another object; it does not mutate any objects.
The part you are reading about strong references and "override this behavior" has to do with the separate issue of memory management behavior of blocks under MRC only. Under MRC, there is no concept of variables being __strong or __weak like in ARC. When a variable of object-pointer type is captured by a block in MRC, it is by default captured as a strong reference (the block retains it, and releases it when the block is deallocated), because that is the desired behavior most of the time. If you wanted the block to not retain the captured variable, the only way to do that was to make it __block, which not only made the variable shared between the two scopes, but also made the block not retain the variable. So the two concepts were conflated in MRC.
In ARC, whether a block captures a variable strongly or weakly depends on the captured variable being __strong or __weak (or __unsafe_unretained), and is completely orthogonal with whether the variable is __block or not. You can have object-pointer variables that are __block without being weakly captured, or weakly captured without being __block, or both weakly captured and __block if you want.
You quote the somewhat dated Blocks Programming Topics, which says:
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
That document dates back to the days of manual reference counting, back before ARC. In manual reference counting code you could use __block to avoid establishing a strong reference to objects referenced inside the block.
But this behavior has changed with ARC, as outlined in Transitioning to ARC Release Notes. We now use weak in those cases where we don't want to establish strong references to the objects referenced in the block. (You can use unsafe_unretained in special cases where you know the resulting dangling pointer isn't a problem.)
So, go ahead and use __block when dealing with fundamental types that you want to mutate inside the block. But when dealing with objects in blocks under ARC, the __block qualifier generally doesn't enter the discussion. The question is simply whether you want a strong reference or a weak one (or an unsafe, unretained one). And that's largely dictated by the object graph of your app, namely (a) whether you need weak/unretained reference to prevent strong reference cycle; or (b) you don't want want some asynchronously executing block to unnecessarily prolong the life of some object referenced in the block. Neither of those situations would appear to be the case here.

Instance variable & properties in blocks

All objects are in the heap, that is obvious, but what about the instance variables?
Do they change the retain count? If yes, can they be directly used and modified in blocks?
I came across a tutorial which says blocks can modify objects that are in the heap. So another question arises: Can we modify a heap object without using
__block before the object type?
You don't need the __block qualifier in order to modify instance variables. You were on the right track in thinking about this. If a thing is on the heap, it's persistent. If it is stack based, like a local variable, it does need to be marked with __block if the block modifies it.

Defining Objective-C blocks as properties - best practice

I've recently come across an Apple document that shows the following property declaration for a block:
#interface XYZObject : NSObject
#property (copy) void (^blockProperty)(void);
#end
Also, this article states:
Note: You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it’s best practice for the property attribute to show the resultant behavior. For more information, see Blocks Programming Topics.
I also read the suggested Blocks Programming Topics but haven't found anything relevant there.
I'm still curious as to why defining a block property as "copy" is best practice. If you have a good answer, please try to distinguish between ARC and MRC differences if there are any.
Thank you
By default blocks are created on the stack. Meaning they only exist in the scope they have been created in.
In case you want to access them later they have to be copied to the heap by sending a copy message to the block object. ARC will do this for you as soon as it detects a block needs to be accessed outside the scope its created in. As a best practise you declare any block property as copy because that's the way it should be under automatic memory management.
Read Stack and Heap Objects in Objective-C by Mike Ash for more info on stack vs. heap.
Blocks are, by default, allocated on the stack. This is an optimization, since stack allocation is much cheaper than heap allocation. Stack allocation means that, by default again, a block will cease to exist when the scope in which it is declared exits. So a block property with retain semantics will result in a dangling pointer to a block that doesn't exist anymore.
To move a block from the stack to the heap (and thus give it normal Objective-C memory management semantics and an extended lifetime), you must copy the block via [theBlock copy], Block_copy(theBlock), etc. Once on the heap, the block's lifetime can be managed as needed by retaining/releasing it. (Yes, this applies in ARC too, you just don't have to call -retain/-release yourself.)
So you want to declare block properties with copy semantics so the block is copied when the property is set, avoiding a dangling pointer to a stack-based block.
The "best practices" you refer to simply say, "Seeing as ARC is going to magically copy your block no matter what you write here, it's best you explicitly write 'copy' so as not to confuse future generations looking at your code."
Explanation follows:
Typically, you shouldn’t need to copy (or retain) a block. You only need to make a copy when you expect the block to be used after destruction of the scope within which it was declared. Copying moves a block to the heap.
–Blocks Programming Topics: Using Blocks, Copying Blocks
Clearly, assigning a block to a property means it could be used after the scope it was declared in has been destroyed. Thus, according to Blocks Programming Topics that block should be copied to the heap with Block_copy.
But ARC takes care of this for you:
Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more.
–Transitioning to ARC
Note that this isn't about the retain semantics the block. There's simply no way for the block's context to exist without being moved off the (soon-to-be-popped) stack and on to the heap. So regardless of what attributes you qualify your #property with, ARC is still going to copy the block.

What's the rule of "__block Variables" memory management?

I read the "Blocks Programming Topics" ducument. But I'm not very clear about the __block Variables's management.
When the __block Variables is a type of standard C scalar(like int, double), everything is Ok. But if it is a object. When I copy the related block variable using Block_copy(). I found the object's retainCount is always 1. So how can I manage the memory? Whether I only need to do is manage the related block variable use Block_release, and the runtime system will take care of the __block Variables.
I'm not a native Engnish speaker, I hope you can understand me.
In non-ARC case __block modifier don't increase retainCount. You have to manually manage the lifetime of the object

Naming convention of instance variables when synthesizing properties

When synthesizing properties in Objective-C, it's recommended that you dont simply write:
#synthesize window;
but rather
#synthesize window = _window;
The reasoning is that you don't want your instance variable named the same as your getter method or "bad things can happen".
I've always used #synthesize var1, var2, etc in my apps without "bad things" happening. What sort of bad things could happen?
Bad things used to happen, particularly in the pre-ARC days when people would assign objects to the storage iVar instead of the property. If this was done by accident, then the memory management implied by the synthesized setter wouldn't be applied, leading to leaks, or premature releases.
I use to do it the simple way, but now I use prefixes. I don't declare my iVar themselves anymore, I let the modern runtime take care of that for me. I use prefixes so that I don't accidentally use an iVar like a local variable.
Also - I tend to refer to my properties as self.iVar almost everywhere in my classes. This is so that I can use lazy loaded properties when I want to without worrying about which ones are and are not lazily loaded.
The biggest reason for using the leading underscore in instance variables (like _myProperty) is that when people read the code with the leading underscore, they know that you are using an instance variable, not a local variable, a global variable, or forgot to write "self." like self.myProperty, and that you did this intentionally.
Before ARC, _myProperty wouldn't do any reference counting, while self.myProperty would (for "retain" / "strong" properties). With ARC when you are using "copy" properties, _myProperty does reference counting but still does no copying, so there is still some difference. The most important difference is that _myProperty won't trigger any observers.

Resources