"Retain'ed block property does not copy the block - use copy attribute instead - objective-c

I come from a heavy JavaScript-oriented background and I'm transitioning as best I can into Objective-C. Naturally, I always find myself jumping at the opportunity to utilize closure functions in my source code, such as:
#property (nonatomic, retain) void (^zoomCallback)(NSInteger width, NSInteger height, NSString *url);
However, each time I jot this into Xcode, it warns me:
Retain'ed block property does not copy the block - use copy attribute instead
It was my understanding that you no longer have to retain things manually anymore in Objective-C due to ARC, so I'm admittedly rather thrown by this warning. I'm assuming by block it's referring to my closure function, so as far as I can interpret it's telling me that assigning this variable:
myObject.zoomCallback = someMethod;
Would also cause someMethod to be retained, and thus the owner of someMethod to continue to exist? Did I get that right?
What are the negative repercussions of this? If I "copy" the block, wont it allow for the owner of someMethod to be destroyed, and thus within the closure method itself any time I refer to "self" it will no longer exist? Don't I almost always want to retain the block unless my closure method is doing something very trivial or something that doesn't reference member variables or methods?

Blocks need to be copied before they are stored (and in some cases just before you use them, but that's usually a strange bit of code) because blocks are created on the stack and need to be moved to the heap. If the block isn't copied and the context in which it was created is destroyed then it won't always work properly. This is the case when the block captures some external variables (instead of only using the passed parameters).

Related

Is it safe to pass local variables as method parameters inside of a block?

I know blocks in Obj-C allow you to reference local variables, which is nice. But can we safely pass local variables to another method from inside of a block?
I know referencing self can be dangerous from inside blocks, but does this extend to any other variables.
Example:
-(void)methodTakesObject(ObjectA *)object {
ObjectB *b = object.b;
__weak MyObject *weakSelf = self;
[b doInBackground:^(NSArray *results) {
[weakSelf doSomethingElseWith:results andWith:object andEvenWith:b];
}
}
There are three "types" of local variables here. the results from the block, the ObjectB created inside the method, and an ObjectA which was passed to the method to start.
Should I be concerned about using any of these variables, and indeed is there any difference/concerns between how these variables are treated from within the block
In fact, it makes no difference no matter what variables are involved.
The concern with a retain cycle is if an object holds a strong reference to a block that it isn't expected to release until it is deallocated while the block holds a strong reference to that same object. That's not happening here.
A method called -doInBackground: seems like it will run the block (starting immediately-ish) and then release the block when it finishes. So, there's no prospect of the block being kept around as long as some other object exists, thus there's no prospect of it keeping that other object around forever.
You don't even need to use the weak-self convention to avoid a retain cycle here. You would only use it in the unlikely case that you really want to allow self to sometimes be deallocated before the block calls its method. More likely, you should just use a normal, strong reference to self because it's normal and/or desirable for self to live long enough for the block to execute.
If you are worried about retain cycle, #ken gave you the perfect answer. As for the concerns about variables:
object is retained from the method that called
methodTakesObject: so you don't have to worry about it. (if it isn't nil, tho).
b is also retained by you, the reference count is likely 2 or
more, so you also don't have to worry about it.
In other words, you are safe.

Cocoa blocks as strong pointers vs copy

I did work several times with blocks as with pointers to which i had strong reference
I heard that you should use copy, but what is the implication in working with blocks as pointers and not with the raw object?
I never got a complain from the compiler, that i should not use
#property (nonatomic, strong) MyBlock block;
but should use
#property (nonatomic, copy) MyBlock block;
as far as i know, the block is just an object, so why to preferrer copy anyway?
Short Answer
The answer is it is historical, you are completely correct that in current ARC code there is no need to use copy and a strong property is fine. The same goes for instance, local and global variables.
Long Answer
Unlike other objects a block may be stored on the stack, this is an implementation optimisation and as such should, like other compiler optimisations, not have direct impact on the written code. This optimisation benefits a common case where a block is created, passed as a method/function argument, used by that function, and then discarded - the block can be quickly allocated on the stack and then disposed of without the heap (dynamic memory pool) being involved.
Compare this to local variables, which (a) created on the stack, (b) are automatically destroyed when the owning function/method returns and (c) can be passed-by-address to methods/functions called by the owning function. The address of a local variable cannot be stored and used after its owning function/method has return - the variable no longer exists.
However objects are expected to outlast their creating function/method (if required), so unlike local variables they are allocated on the heap and are not automatically destroyed based on their creating function/method returning but rather based on whether they are still needed - and "need" here is determined automatically by ARC these days.
Creating a block on the stack may optimise a common case but it also causes a problem - if the block needs to outlast its creator, as objects often do, then it must be moved to the heap before its creators stack is destroyed.
When the block implementation was first released the optimisation of storing blocks on the stack was made visible to programmers as the compiler at that time was unable to automatically handle moving the block to the heap when needed - programmers had to use a function block_copy() to do it themselves.
While this approach might not be out-of-place in the low-level C world (and blocks are C construct), having high-level Objective-C programmers manually manage a compiler optimisation is really not good. As Apple released newer versions of the compiler improvements where made. Early on it programmers were told they could replace block_copy(block) with [block copy], fitting in with normal Objective-C objects. Then the compiler started to automatically copy blocks off stack as needed, but this was not always officially documented.
There has been no need to manually copy blocks off the stack for a while, though Apple cannot shrug off its origins and refers to doing so as "best practice" - which is certainly debatable. In the latest version, Sept 2014, of Apple's Working with Blocks, they stated that block-valued properties should use copy, but then immediately come clean (emphasis added):
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.
There is no need to "show the resultant behavior" - storing the block on the stack in the first place is an optimisation and should be transparent to the code - just like other compiler optimisations the code should gain the performance benefit without the programmer's involvement.
So as long as you use ARC and the current Clang compilers you can treat blocks like other objects, and as blocks are immutable that means you don't need to copy them. Trust Apple, even if they appear to be nostalgic for the "good old days when we did things by hand" and encourage you to leave historical reminders in your code, copy is not needed.
Your intuition was right.
You are asking about the ownership modifier for a property. This affects the synthesized (or auto-synthesized) getter and/or setter for the property if it is synthesized (or auto-synthesized).
The answer to this question will differ between MRC and ARC.
In MRC, property ownership modifiers include assign, retain, and copy. strong was introduced with ARC, and when strong is used in MRC, it is synonymous with retain. So the question would be about the difference between retain and copy, and there is a lot of difference, because copy's setter saves a copy of the given value.
Blocks need to be copied to be used outside the scope where it was created (with a block literal). Since your property will be storing the value as an instance variable that persists across function calls, and it's possible that someone will assign an unoccupied block from the scope where it was created, the convention is that you must copy it. copy is the right ownership modifier.
In ARC, strong makes the underlying instance variable __strong, and copy also makes it __strong and adds copying semantics to the setter. However, ARC also guarantees that whenever a value is saved into a __strong variable of block-pointer type, a copy is done. Your property has type MyBlock, which I assume is a typedef for a block pointer type. Therefore, a copy will still be done in the setter if the ownership qualifier were strong. So, in ARC, there is no difference between using strong and copy for this property.
If this declaration might be used in both MRC and ARC though (e.g. a header in a library), it would be a good idea to use copy so that it works correctly in both cases.
what is the implication in working with blocks as pointers and not with the raw object?
You are never using the raw value, you always have a pointer to a block: a block is an object.
Looking at your specific example, I am assuming you want to keep the block around, "so why to preferrer copy anyway"enter code here? Well, it's a matter of safety (this example is taken from Mike Ash blog). Since blocks are allocated on the stack (and not on the heap as the rest of the objects in objective-c), when you do something like this:
[dictionary setObject: ^{ printf("hey hey\n"); } forKey: key];
You are allocating the block on the stack frame of your current scope, so when the scope ends (for example your returning the dictionary), the stack frame is destroyed and the block goes with it. So you got yourself a dangling pointer. I would advise reading Mike's article fully. Anyway, you can go with a strong property if when you are assigning the block you copy it:
self.block = [^{} copy];
Edit: After looking at Mike's article date, I am assuming this was the behaviour Pre-ARC. On ARC it seems it's working as expected, and it won't crash.
Edit2: After experimenting with Non-ARC it doesn't crash as well. But this example shows different results depending on the use of ARC or not:
void (^block[10])();
int i = -1;
while(++i < 10)
block[i] = ^{ printf("%d\n", i); };
for(i = 0; i < 10; i++)
block[i]();
Quoting Mike Ashe on the different outcomes:
The reason it prints out ten 9s in the first case is quite simple: the
block that's created within the loop has a lifetime that's tied to the
loop's inner scope. The block is destroyed at the next iteration of
the loop, and when leaving the loop. Of course, "destroy" just means
that its slot on the stack is available to be overwritten. It just
happens that the compiler reuses the same slot each time through the
loop, so in the end, the array is filled with identical pointers, and
thus you get identical behavior.
As far as I understand copy is required when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
On the other hand, strong means that you own the object until it is needed. It is a replacement for the retain attribute, as part of ARC.
Source: Objective-C declared #property attributes (nonatomic, copy, strong, weak)
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.

Retaining/Copy Block Arc [iOS]

I have seen a lot of answers around, but I couldn't find any solution for my problem.
I basically have a Class where I only use class methods. I never allocate this class. So, I am passing a block to it and storing it on a static on the .h of the class, like this:
static ErrorBlock _errorBlock;
I am storing this way:
_errorBlock = [errorBlock copy];
I receive errorBlock as a parameter of a method. After some calculations, I invoke the block like this:
_errorBlock(error);
It's worth saying that I am invoking this from a Class's Category. The application basically returns:
EXC_BAD_ACCESSS(code=2, adress = 0xc)
When I check the _errorBlock value, it's nil. So my question is, how can I keep a live reference to the block?
If _errorBlock is "nil" it might be safe to say that it was assigned with nil and there is no reference to keep it alive. If you create a reference as in NSObject *reference = someObject and someObject is released your reference pointer will still point to location where someObject used to be and should not be nil. Check if you have some problems with assigning the block or if it even gets called. Also you might want to check if _errorBlock exists before calling it.
I was able to work it out, my removing completely the use of global blocks. At the moment I use the blocks my passing them as parameters.

Passing blocks in Objective-C

When writing a method that accepts a block as an argument, do I need to do anything special such as copying the block to the heap before executing it? For example, if I had the following method:
- (void)testWithBlock:(void (^)(NSString *))block {
NSString *testString = #"Test";
block(testString);
}
Should I do anything with block before calling it, or when entering the method? Or is the above the correct way of using the passed-in block? Also, is the following way of calling the method correct, or should I do something with the block before passing it?
[object testWithBlock:^(NSString *test){
NSLog(#"[%#]", test);
}];
Where do I need to copy the block? And how would this have been different if I wasn't using ARC?
When you receive a block as a method parameter, that block could be the original that had been created on the stack or it could be copy (a block on the heap). As far as I'm aware, there's no way tell. So the general rule of thumb is if you're going to execute the block within the method that's receiving it, you don't need to copy it. If you intend to pass that block to another method (which may or may not execute it immediately) then you also don't need to copy it (the receiving method should copy it if it intends to keep it around). However, if you intend to store the block in any way for some place for later execution, you need to copy it. The primary example many people use is some sort of completion block held as an instance variable:
typedef void (^IDBlock) (id);
#implementation MyClass{
IDBlock _completionBlock;
}
However, you also need to copy it if you're going to add it to any kind of collection class, like an NSArray or NSDictionary. Otherwise, you'll get errors (most likely EXC_BAD_ACCESS) or possibly data corruption when you try to execute the block later.
When you execute a block, it's important to test first if the block is nil. Objective-c will allow you to pass nil to a block method parameter. If that block is nil, you'll get EXC_BAD_ACCESS when you try to execute it. Luckily this is easy to do. In your example, you'd write:
- (void)testWithBlock:(void (^)(NSString *))block {
NSString *testString = #"Test";
if (block) block(testString);
}
There are performance considerations in copying blocks. Compared to creating a block on the stack, copying a block to the heap is not trivial. It's not a major deal in general, but if you're using a block iteratively or using a bunch of blocks iteratively and copying them on each execution, it'll create a performance hit. So if your method - (void)testWithBlock:(void (^)(NSString *))block; were in some kind of loop, copying that block might hurt your performance if you don't need to copy it.
Another place you need to copy a block is if you intend on calling that block in itself (block recursion). This isn't all that common, but you must copy the block if you intend to do this. See my question/answer on SO here: Recursive Blocks In Objective-C.
Finally, if you're going to store a block you need to be really careful about creating retain cycles. Blocks will retain any object passed into it, and if that object is an instance variable, it will retain the instance variable's class (self). I personally love blocks and use them all the time. But there's a reason Apple doesn't use/store blocks for their UIKit classes and instead stick with either a target/action or delegate pattern. If you (the class creating the block) are retaining the class that is receiving/copying/storing the block, and in that block you reference either yourself or ANY class instance variable, you've created a retain cycle (classA -> classB -> block -> classA). This is remarkably easy to do, and it's something I've done too many times. Moreover, "Leaks" in Instruments doesn't catch it. The method to get around this is easy: simply create a temporary __weak variable (for ARC) or __block variable (non-ARC) and the block won't retain that variable. So,for example, the following would be a retain cycle if the 'object' copies/stores the block:
[object testWithBlock:^(NSString *test){
_iVar = test;
NSLog(#"[%#]", test);
}];
However, to fix this (using ARC):
__weak IVarClass *iVar = _iVar;
[object testWithBlock:^(NSString *test){
iVar = test;
NSLog(#"[%#]", test);
}];
You can also do something like this:
__weak ClassOfSelf _self = self;
[object testWithBlock:^(NSString *test){
_self->_iVar = test;
NSLog(#"[%#]", test);
}];
Note that many people don't like the above because they consider it fragile, but it is a valid way of accessing variables.
Update - The current compiler now warns if you try to directly access a variable using '->'. For this reason (as well as reasons of safety) it's best to create a property for the variables you want to access. So instead of _self->_iVar = test; you would use: _self.iVar = test;.
UPDATE (more info)
Generally, it's best to consider the method that receives the block as responsible for determining whether the block needs to be copied rather than the caller. This is because the receiving method can be the only one that knows just how long the block needs to be kept alive or if it needs to be copied. You (as the programmer) will obviously know this information when you write the call, but if you mentally consider the caller and receiver at separate objects, the caller gives the receiver the block and is done with it. Therefore, it shouldn't need to know what is done with the block after it's gone. On the flip side, it's quite possible that the caller may have already copied the block (maybe it stored the block and is now handing it off to another method) but the receiver (who also intends on storing the block) should still copy the block (even though the block as already been copied). The receiver can't know that the block has already been copied, and some blocks it receives may be copied while others may not be. Therefore the receiver should always copy a block it intends on keeping around? Make sense? This essentially is good Object Oriented Design Practices. Basically, whoever has the information is responsible for handling it.
Blocks are used extensively in Apple's GCD (Grand Central Dispatch) to easily enable multi-threading. In general, you don't need to copy a block when you dispatch it on GCD. Oddly, this is slightly counter-intuitive (if you think about it) because if you dispatch a block asynchronously, often the method the block was created in will return before the block has executed, which generally would mean the block would expire since it is a stack object. I don't think that GCD copies the block to the stack (I read that somewhere but have been unable to find it again), instead I think the life of the thread is extended by being put on another thread.
Mike Ash has extensive articles on blocks, GCD and ARC which you may find useful:
Mike Ash: Practical Blocks
Mike Ash: Objective-C Blocks vs C++0x Lambdas: Fight!
Mike Ash: Q&A - More info on Blocks
Mike Ash: Automatic Reference Counting He talks about blocks & ARC in this article.
Mike Ash: GCD Is Not Blocks, Blocks Are Not GCD
Apple Docs - Introducing Block & GCD
This all looks good. Though, you might want to double-check the block parameter:
#property id myObject;
#property (copy) void (^myBlock)(NSString *);
....
- (void)testWithBlock: (void (^)(NSString *))block
{
NSString *testString = #"Test";
if (block)
{
block(test);
myObject = Block_copy(block);
myBlock = block;
}
}
...
[object testWithBlock: ^(NSString *test)
{
NSLog(#"[%#]", test);
}];
Should be fine. And I believe that they are even trying to phase out Block_copy(), but they haven't yet.
As the blocks programming topics guide says under 'Copying Blocks':
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.
In the case you are describing, you can basically think about the block as simply being a parameter to your method, just like as if it were an int or other primitive type. When the method gets called, space on the stack will be allocated for the method parameters and so the block will live on the stack during the entire execution of your method (just like all the other parameters). When the stack frame gets popped off the top of the stack at the return of the method, the stack memory allocated to the block will be deallocated. Thus, during the execution of your method, the block is guaranteed to be alive, so there's no memory management to deal with here (in both ARC and non-ARC cases). In other words, your code is fine. You can simply call the block inside the method.
As the quoted text suggests, the only time you need to explicitly copy a block is when you want it to be accessible from outside of the scope where it was created (in your case, beyond the lifetime of the stack frame of your method). As an example, suppose you want a method that fetches some data from the web, and runs a block of code when the fetch is complete. Your method signature might look like:
- (void)getDataFromURL:(NSURL *)url completionHandler:(void(^)(void))completionHandler;
Since the data fetch happens asynchronously, you would want to keep the block around (likely in a property of your class) and then run the block once the data has been fully fetched. In this case, your implementation might look like:
#interface MyClass
#property (nonatomic, copy) void(^dataCompletion)(NSData *);
#end
#implementation MyClass
#synthesize dataCompletion = _dataCompletion;
- (void)getDataFromURL:(NSURL *)url completionHandler:(void(^)(NSData *fetchedData))completionHandler {
self.dataCompletion = completionHandler;
[self fetchDataFromURL:url];
}
- (void)fetchDataFromURL:(NSURL *)url {
// Data fetch starts here
}
- (void)finishedFetchingData:(NSData *)fetchedData {
// Called when the data is done being fetched
self.dataCompletion(fetchedData)
self.dataCompletion = nil;
}
In this example, using a property with a copy semantic will perform a Block_copy() on the block and copy it to the heap. This happens in the line self.dataCompletion = completionHandler. Thus, the block gets moved from the stack frame of the -getDataFromURL:completionHandler: method to the heap which allows it to be called later in the finishedFetchingData: method. In the latter method, the line self.dataCompletion = nil nullifies the property and sends a Block_release() to the stored block, thus deallocating it.
Using a property in this way is nice since it will essentially handle all of the block memory management for you (just make sure it's a copy (or strong) property and not simply a retain) and will work in both non-ARC and ARC cases. If instead you wanted to use a raw instance variable to store your block and were working in a non-ARC environment, you would have to call Block_copy(), Block_retain(), and Block_release() yourself in all the proper places if you wanted to keep the block around any longer than the lifetime of the method in which it's passed as a parameter. The same code above written using an ivar instead of a property would look like this:
#interface MyClass {
void(^dataCompletion)(NSData *);
}
#end
#implementation MyClass
- (void)getDataFromURL:(NSURL *)url completionHandler:(void(^)(NSData *fetchedData))completionHandler {
dataCompletion = Block_copy(completionHandler);
[self fetchDataFromURL:url];
}
- (void)fetchDataFromURL:(NSURL *)url {
// Data fetch starts here
}
- (void)finishedFetchingData:(NSData *)fetchedData {
// Called when the data is done being fetched
dataCompletion(fetchedData)
Block_release(dataCompletion);
dataCompletion = nil;
}
You know there are two kinds of blocks:
blocks stored in the stack, the ones that you explicitly write as ^{...}, and that disappear as soon as the function they are created in returns, just as regular stack variables. When you call a stack block after the function it belonged to has returned, bad things happens.
blocks in the heap, the ones that you get when you copy another block, the ones that live as long as some other object keeps a reference to them, just like regular objects.
The only reason for you to copy a block is when you are given a block that is, or may be a stack block (explicit local block ^{...}, or method argument whose origin you don't know), AND that you want to extend its life span out of the limited one of the stack blocks, AND that the compiler doesn't already do that job for you.
Think: keeping a block in an instance variable.
Adding a block in a collection such as NSArray.
Those are common examples of cases where you should copy a block when you're not sure it is already a heap block.
Note that the compiler does it for you when a block is called in another block.

Is it possible to have a memory leak under ARC by passing a block as an argument and then copying it? If so, how to prevent it?

I'm working on a Objective-C project and we have ARC enabled. I'm currently dealing with two separate classes, let's call them A and B.
A has a strong reference to B and B has a block property with the copy attribute.
#interface A {
B *b;
...
}
#end
#interface B {
...
}
#property (copy) void (^myBlock)();
#end
Now, if inside a method owned by A I try to assign to myBlock:
b.myBlock = ^{ [self doSomething] };
The compiler (correctly) complains:
Capturing 'self' strongly in this block is likely to lead to a retain cycle.
I understand this behaviour and how to work around it, based on the answers to this question. (Basically, a cycle is formed because once the block is copied it will contain a strong reference to A, which has a strong reference to B, which in turn has a strong reference to the block itself.)
Now, if instead of directly assigning the block to the property I pass it to a method of B:
[b takeMyBlock:^{ [self doSomething] }];
And inside that method I do the assignment, the compiler will no longer complain.
My question is: Will that create a memory leak? If so, how to avoid it? Is it possible to annotate the method argument somehow so that the compiler knows the argument is going to be copied?
Thanks in advance.
I just encountered the same issue myself. While the issue didn't manifest itself as a leak per se, I actually found the problem while analysing heap growth using the Allocations tool in Instruments -- so it obviously does cause a memory issue.
I think the compiler would have to be pretty smart to pick up on the problem and issue a warning, so my guess is that one of two approaches is needed:
Documentation: As you suggested in your question, clearly document
that this method will copy the block passed to it. This might
involve naming the block parameter something like blockToCopy
(Xcode helpfully displays the block parameter name when using
autocompletion). Also, comment the method declaration. If you're
using a documentation tool like appledoc this is particularly nice,
as your documentation will also appear in Xcode's quick help dialog
when option clicking your code.
Never capture self strongly in a block: This is perhaps best
practise, as I don't think it's ever a good idea to keep a strong
reference to self inside a block. If you have to reference self,
use a weak reference. This will certainly avoid the situation you
describe. (N.B. referencing an instance variable will also keep a strong
reference to self).
In ARC, what it does is if a local variable or a WEAK variable loses it reference. The memory will be dealloced immediately since its reference count is zero. However, if you are reallocating a STRONG variable, it will definitely cause a memory leak for strong variable retains even if reference count decays to zero. In this case, you shall set this variable to NIL before reallocation or set the variable to weak if strong property is unnecessary.