Under ARC, are Blocks automatically copied when assigned to an ivar directly? - objective-c

Assume the following code under ARC,
typedef void (^MyResponseHandler) (NSError *error);
#interface MyClass : NSObject
{
MyResponseHandler _ivarResponseHandler;
}
- (void)myMethod:(MyResponseHandler)responseHandler
{
_ivarResponseHandler = responseHandler;
...
}
Question: Is the block automatically copied to the heap when assigned to the ivar?
My previous question implied that it is copied when assigned through a #property. But, today I used the above code and received an EXC_BAD_ACCESS that was fixed by changing to
_ivarResponseHandler = [responseHandler copy].

Edit: My previous answer was likely wrong.
Some selected excerpts from the ARC docs say:
3. Retainable object pointers
A retainable object pointer (or retainable pointer) is a value of a retainable object pointer type (retainable type). There are three kinds of retainable object pointer types:
block pointers (formed by applying the caret (^) declarator sigil to a function type)
4.2. Semantics
Assignment occurs when evaluating an assignment operator. The semantics vary based on the qualification:
For __strong objects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; and finally, the old pointee is released. This is not performed atomically; external synchronization must be used to make this safe in the face of concurrent loads and stores.
4.4.1. Objects
If an object is declared with retainable object owner type, but without an explicit ownership qualifier, its type is implicitly adjusted to have __strong qualification.
7.5. Blocks
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
So I think the answer is maybe, depending on the optimizer.

Your problem and solution indicate that my answer to your other question was probably wrong. I based it on the last paragraph of section 7.5 of the clang Objective-C Automatic Reference Counting documentation:
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
I took “these semantics” to mean the whole document, but if “these semantics” to refers to only section 7.5, then ARC only inserts a Block_copy for a block that is captured by a block.

Related

How to declare a double pointer property in Objective-C?

I have a function declared like this:
- (void)loadWithCompletion:(MyCompletion)completion error:(NSError**)error;
The function takes a double pointer to an NSError so I can report errors to the caller. The completion (and possibly the error) will occur some time after the function is called. I need to store the NSError** as a property so I can use it when the aforementioned time passes.
#property(nonatomic, assign) NSError** error;
This property declaration gives me the error:
Pointer to non-const type NSError* with no explicit ownership.
add __autoreleasing between the **, to give NSError*__autoreleasing* error
In Xcode 5.1 the ARC warning "Implicit ownership types on out parameters" was turned on by default (it used to be off). So with 5.1 this warning started appearing when there was no specified ownership.
The compiler assumes you want autoreleased, which is usually correct, but it's better that the author think about it and specify what the really want.
Usually you want the output parameter to be autoreleasing, similar to a function result. The caller will get an autoreleased object and will need to store it in a strong variable if they want to retain ownership.

Why are Objective-C blocks not handled through pointers as are other Objective-C objects?

In code that uses blocks, you frequently see declarations such as:
typedef void(^Thunk)(void);
Thunk block1 = ^{NSLog(#"%d %p",i, &i);};
instead of
typedef void(^Thunk)(void);
Thunk *block1 = ^{NSLog(#"%d %p",i, &i);};
Blocks seem to be the only Objective-C object that is handled directly, instead of through a pointer. Why is this? Aren't they regular objects?
If you're wondering about the missing *: In your example you typedef'd the block which is hiding the syntax. You can do this with other objects as well:
typedef NSNumber *Number;
Number foo = #42;
When assigning a block to a variable that's actually assigning a pointer.
Blocks are a bit like C arrays: Block literals are structures created by the compiler. Block variables are pointers behind the scenes.
You're not handling a block “directly”. You're handling it indirectly.
The syntax void (^)(void) declares a pointer to a block. There is no syntax for type “block”; there is only syntax for type “pointer to a block”.
From the Language Specification for Blocks:
The abstract declarator,
int (^)(char, float)
describes a reference to a Block that, when invoked, takes two parameters, the first of type char and the second of type float, and returns a value of type int. The Block referenced is of opaque data that may reside in automatic (stack) memory, global memory, or heap memory.
The relevant bit is “describes a reference to a Block”.
The specification isn't entirely consistent, since (for example) it refers to a “variable with Block type” and “Block variable declarations“. But in fact a variable always holds a reference (pointer) to a block, and never holds a block directly as its value.
If you look at the block implementation, you will see that blocks are ObjC objects.
If you inspect a stack block (like in your example), you'll see something like this:
(lldb) po myBlock
<__NSStackBlock__: 0xbfffc940>
And you will notice in the public header _Block_copy() and _Block_release() take void* arguments.
The non-pointeryness is just syntactic sugar the compiler provides to shield you from the dirty bits of blocks.
Blocks are a C extension. You can use blocks in C (where the extension is supported).
Apple just happens to have implemented blocks using ObjC types.
Implementation details: Blocks are one of the few ObjC types which may be allocated on the stack using clang. Normally, this is not an option because almost every API expects that an objc_object is a heap allocation which supports reference counting.

NSError and __autoreleasing

Can someone please explain to me the purpose of having __autoreleasing in the following sample code block?
- (void)execute:(NSError * __autoreleasing *)error {
// do stuff, possibly assigning error if something went wrong
}
I removed the __autoreleasing and everything still seems to compile/run fine. I started using obj-c post ARC so I never really learned/understood all those double underscore thingamajigs. I've read the ARC transition guide, but I don't fully understand their NSError example.
Consider how ARC works with variables - each reference variable has a mode (implicit or explicit): strong, weak, etc. This mode let's ARC know how to handle reads and writes to that variable; e.g. for a strong variable reading requires no additional action while writing requires releasing the existing reference in the variable before it is replaced by the new one. ARC needs to know the mode of any variable in order to function.
Now consider variables that themselves are passed by reference, e.g. for your execute you'll have a call along the lines of:
NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value
and the body of execute will contain an assignment along the lines of:
- (void)execute:(NSError * __autoreleasing *)error
{
...
if (error != NULL)
*error = [NSError ...]; // assign indirectly via the reference to a variable
...
}
Now for that indirect assignment ARC needs to know the mode of the referenced variable so it knows how to read and write. That is what the __autoreleasing is in the declaration, it tells ARC that it has been passed a reference to a variable whose mode is autoreleasing, and that tells ARC how to read and write the contents of the variable. Remove the __autoreleasing and a default mode will be assumed, and in this case I'd suggest being explicit is certainly good.
The autoreleasing mode means the variable contains a reference which is not owned, reads should retain if necessary and writes can just write. It is used mainly for variables passed by reference.
You might notice that in the example above the variable myError has mode strong (implicitly) and yet it is passed by reference as autoreleasing - the compiler handles this automatically by introducing a temporary autoreleasing variable, copying without retaining the current reference in myError into it, and passing the temporary by reference as the argument to execute:. After the call returns the compiler does a normal assignment from the temporary to myError, which results in any old reference being released and the returned one retained.
For more details see Apple's Transitioning to ARC Release Notes
Followup to Comments
Q: Is __autoreleasing implicitly set?
A: Well Apple's document is not specific, but the Clang documentation says it is implicit for indirect parameters. As above I'd recommend being explicit, clarity is a Good Thing™.
Q: Does the placement matter?
A: Yes, and no... This is a C declaration, the stuff of quiz questions ("What does the following declare..."). The qualifier should be between the two asterisks as it is a pointer to a (variable of type) autoreleasing pointer to an object, but Apple state the compiler is "forgiving" without being specific of what it forgives. Play it safe, put it in the right place.
Q: Should you not test for error being NULL before doing the indirect assignment?
A: Of course you should, somewhere before you do the indirection. The code shown is just an outline and such detail was elided and covered by the ...’s. However as it has been raised a few times over the years maybe I elided too much, a suitable if has been added.

iOS 5 Blocks ARC bridged cast

This Question references this Question:
How to simplify callback logic with a Block?
My header has these typedefs
typedef void (^StuffDoneBlock)(NSDictionary * parsedData);
typedef void (^StuffFailedBlock)(NSError * error);
And in init
stuffDoneCallback = Block_copy(done);
StuffFailedCallback = Block_copy(error);
In this paper its says that Block_copy is unnecessary. But then it needs a bridged cast.
The compiler message is at follows:
error: cast of block pointer type 'StuffDoneBlock' (aka 'void (^)(NSDictionary *__strong)') to C pointer type 'const void *' requires a bridged cast [4]
stuffDoneCallback = _bridge(Block_copy(done));
^~~~~~~~~~~~~~~~
/Developer-4.2/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/include/Block.h:60:61: note: instantiated from:
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
^~~~~~~~~~~~~~~~~~~~~~~~~~~
First off, why are you even using Block_copy()? Unless you're writing raw C, you should be calling -copy on the block instead, as in [done copy]. Secondly, ARC will copy blocks for you that need to live past their initialization scope[1], so you don't need to even call -copy anymore. The only "exception" is that block-typed properties still need to have the copy attribute.
[1]: Clarification appears to be needed here. ARC only implicitly copies blocks when the compiler sees that it needs to live past its initialization scope. This basically means when it's assigned to a variable that escapes the current scope (stack variable declared in a parent scope, instance variable, static, etc.). However, if it's passed as an argument to a method/function, the compiler does not do any automatic copying. Typically this isn't a problem because block-aware methods/functions that need to hold onto the block past the stack frame (dispatch_async(), completion blocks, etc.) will copy them for you. However, APIs that are not block-aware (such as NSArray) will not implicitly copy the block, since they expect that a simple -retain will do the trick. If you're passing your block to a non-block-aware API and the block needs to live past the current scope, you must use an explicit -copy.

Why retain a static variable?

Isn't it unnecessary to retain a static variable since it stays around for the duration of the program, no matter if you release it?
See this code:
https://github.com/magicalpanda/MagicalRecord/blob/master/Source/Categories/NSManagedObjectContext+MagicalRecord.m#L24-29
I'm assuming you mean a static object pointer, such as static NSString *foobar;.
Such variables indeed have a lifetime as long as the application, but the variables we're talking about are pointers only. In Objective-C, objects are always dynamically allocated, and so we always address them with a pointer to their type, but the underlying data for an object is still present out in the dynamically allocated wild blue yonder.
You must still retain the object because, while the pointer to the object will never go out of scope, the object itself can be deallocated just like any other object, and so your pointer will end up pointing to garbage, or worse, another unrelated object.
A simplified version of Jonathan Grynspan's accepted answer:
The retain isn't for the variable which points to an object. That variable will last forever because it's static. The retain is for the object the variable points to. Without the retain the object could (and should) be deallocated. Then you've got a variable pointing to a thing which will cause a sigabrt. This variable pointing nowhere is known as a "dangling pointer."
For the ARC context, the best thing to do is declare the static variable as strong, so something like this:
static ThatClass * __strong thatStaticVariable;
This ensures that the object that thatStaticVariable points to will be a valid object (i.e., never gets deallocated) once assigned. However, you don't actually need the __strong keyword at all, because it's the default (so sayeth the docs, thanks to #zpasternack), so just use
static ThatClass *thatStaticVariable;
and you're good.
Note: forever = while the application is running