How do you handle 'require( ..., bail)' statements with ARC? - objective-c

I'm looking through some of the sample code for the Square Cam in Apple's sample code. I want to replicate some of it's functionality in a modern project using ARC. However, there are a ton of require statements such as:
BOOL success = (destination != NULL);
require(success, bail);
Which generates the compiler error:
Goto into protected scope.
My question is -- what is the appropriate way to handle such statements in a project using ARC?

I had the same problem (with the same sample code). The code looked like this:
BOOL success = (destination != NULL);
require(success, bail);
//Initialise some variables
bail:
//Deal with errors
I added braces around the block with the declarations to make their scope clear:
BOOL success = (destination != NULL);
require(success, bail);
{
// *** Initialise some variables ***
}
bail:
{
//Deal with errors
}
And it solved the problem for me. Through looking at this I also learned you can sometimes expand build errors to get more detail.

Apparently bail is in a scope with one or more __block variables; this is not allowed. See http://clang.llvm.org/compatibility.html#blocks-in-protected-scope for more. The solution proposed there is to limit the scope of the __block variable(s), by putting them in brace-delimited blocks. This may not work always; YMMV.

I am adding some description for #Lewis42 answer.
If you don't put variable in its own scope, you bypass the initialisation of all variable after goto, and when ARC tries to clean it up, it will end up trying to release some random bit of memory.
If you don't want to put variables in their own scope make sure that any variable should not be declared below goto keyword.
Jumps to within __block variable scope
__block require special runtime initialization. A jump into the scope of a __block variable bypasses this initialization, leaving the
variable's metadata in an invalid state.

Related

Try to understand the Objective-C block example

I read some Objective-C code example, and found some code which uses "block" in the the code. I simplify the example a bit so that it is easy to describe.
Given a block in Objective-C
(void)(^myblock)(int num) = ^{
//do something
}
// somewhere in the code
if(myblock) myblock(3);
// do something
My question:
What is the if(myblock) here?
From the protocol of the block which is return void
I would like someone can explain what is the if(myblock) here for?
First of all: Your example is syntactically incorrect. It should be:
void(^myblock)(int num) = // No parenthesis around void
^{
//do something
}
To your Q:
While it is legal to send a message to a nil object reference, it is illegal to call a NULL block pointer. Please, keep in mind that blocks are an extension to (plain) C and such a call would be a dereference of a NULL pointer, which is illegal in C. Therefore such a code would cause a NULL pointer exception. (On OS X EXC_BAD_ACCESS):
void(^myblock)(int num) = NULL;
myblock(3);
Obviously the developer of the snippet could not guarantee that myblock is different from NULL, so he has to check for it. (Or he is simply afraid of this possibility. In such a case I would prefer to have an exception or at least a log message. However, you find that kind of code fuses, that makes things worse instead of better, many, many times.)
It simply tests if myblock is not nil
myblock is a pointer to the lambda function in modern terminology, it's just kind of hidden by the opaque syntax ObjC uses.
So the if tests if the pointer isn't nil. Whether or not that makes sense or if it's superfluous depends on the missing code. Maybe it overwrote the pointer to nil depending on some condition.

No matching function for call to... but only inside a block?

I've got a strange situation. I have some local variables in a function:
JSContext *cx = ...;
jsval successCb = ...;
There is a function call which takes these parameters:
//JS_RemoveValueRoot(JSContext *cx, jsval *vp);
JS_RemoveValueRoot(cx, &successCb); //works
The above compiles fine. However, if I instead have the following, I get a compile time error:
id foo = ^() {
JS_RemoveValueRoot(cx, &successCb);
}
Literally, if I copy and paste the line, if it's outside of the block it compiles, yet if it's not, it doesn't. The error is:
No matching function for call to 'JS_RemoveValueRoot'
I suspect something is going on behind the scenes in terms of how block closures are implemented but I'm not familiar enough with Objective C to figure this out. Why does this generate a compile-time error and how do I fix it?
EDIT: It seems that if I do the following I no longer get a compile-time error, but this makes no sense to me, which is always a bad thing, so I'd still like an explanation...
id foo = ^() {
jsval localSuccessCb = successCb;
JS_RemoveValueRoot(cx, &localSuccessCb);
};
It's more complicated that that. Yes, the immediate issue is that all non-__block captured variables are const inside the block. Therefore, inside the block cx has type JSContext * const and successCb has type const jsval. And const jsval * cannot be passed to jsval *. But you have to first understand why the variables are const.
Blocks capture non-__block variables by value at the time that they are created. That means the copy of the variable inside the block and the copy outside are different, independent variables, even though they have the same name. If it were not const, you might be tempted to change the variable inside the block and expect it to change outside, but it does not. (Of course, the opposite problem still happens -- you can still change the variable outside the block, since it's not const, and wonder why it does not change inside the block.) __block resolves this issue by making it so there's only one copy of the variable, that is shared between the inside and outside of the block.
Then it's important to think about why a const variable is not sufficient. If you just need the value of the variable, then a const copy is just as well. When const won't work, usually it's because of the need to assign to the variable. We need to ask, what does JS_RemoveValueRoot that it requires a non-const pointer to the variable? Is it to assign to the variable? (And if it does, do we care about the new value outside the block? Because if not, we can just assign the const variable to a non-const variable inside the block.)
It turns out it's more complicated. According to the documentation of JS_Remove*Root, it neither uses the value of the variable pointed to, nor needs to set the variable; rather, it needs the address of the variable, and this needs to match the address passed to JS_Add*Root. (Actually, I am not even sure whether a const pointer is even needed for what they're doing.) I am assuming that JS_AddValueRoot was done in the body of the function that encloses the block, outside the block. (I assume this since you said successCb is a local variable, so it must be within this function; if it were within the block, it wouldn't make sense because then successCb could just be a local variable of the block, and thus not need to be captured.)
Because the address of the variable itself is significant, let us consider what happens in the various block variable capture modes. A non-__block variable is now clearly not appropriate, since there are two separate copies (and thus two separate addresses) for the inside and outside. Thus, the addresses given to Add and Remove won't match. A __block variable is shared, and is much better.
However, there is still an issue with __block variables that may make it not match -- the address of a __block variable may change over time! This goes into the specifics of how blocks are implemented. In the current implementation, a __block variable is held in a special structure (a kind of an "object") that starts out on the stack, but when any block capturing it is copied, it is "moved" to the heap as a dynamically-allocated structure. This is very similar to how block objects that capture variables start out on the stack, but is moved to the heap upon being copied. Putting it on the stack first is an optimization, and is not guaranteed to happen; but currently it does. The __block variable itself is actually an access of the variable inside this structure, accessed through a pointer that tracks where this structure is. As the structure is moved from the stack to the heap, you can see the value of the expression &successCb change. (This is not possible in normal C.) Therefore, to have matching addresses, you must ensure that the move has already occurred when you pass the address of the variable to Add. You may be able to do this by forcibly copying a block that captures it.
Ah I believe this is the issue. From this article on closures:
Here comes a first difference. The variables available in a block by closure are typed as «const». It means their values can't be modified from inside the block.
Thus the error is that I was passing JS_RemoveValueRoot a const jsval * instead of a jsval *. Creating a local copy that wasn't constant "resolved" the issue (depending on whether that behavior is acceptable, which in this case it is).
Alternatively I could also declare the jsval as:
__block jsval successCb = ...;
In which case I don't have to create a local non-const copy.
XCode did provide quite the unhelpful error message in this case...

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.

Should I use the __block specifier on an object pointer even though it works without it?

I am using a CAAnimation completion block (using CAAnimationBlocks) to provide processing at the end of an animation and part of that completion block modifies the animated CALayer. This works even if layer isn't declared with the __block specifier, given the object pointer remains constant, however I am really treating the object as read/write.
One aspect of the Apple Guide that bothers me is:
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or
created within the variable’s lexical scope.
Given the layer is a collection iterator, that looks to me like it will actually break if I do use the __block specifier.
Here is the code in question:
for (CALayer *layer in _myLayers) // _myLayers is an ivar of the containing object
{
CAAnimationGroup *group = ...;
...
group.completion = ^(BOOL finished)
{
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
layer.position = [self _findPosition];
[CATransaction commit];
[layer removeAnimationForKey:#"teleportEffect"];
};
[layer addAnimation:group forKey:#"teleportEffect"];
}
My actual question is: Am I doing this right (my spider sense is tingling).
EDIT I should also add that my app uses MRR, however there are no issues with retain/release given the layers are static in nature (their lifetime is that of the containing NSView). Also I appear to be doing precisely what the Patterns to Avoid section of the guide say I shouldn't do, although it's not clear (to me) why.
__block variables are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap.
I don't think that in your case you need a block variable because you are changing the value of the object layer inside the block, since it belong to the _myLayers array that seems to be an instance variable it is difficult that the object will be released before each block performed ... However you can add the __block storage type modifier to retain the object, but if you are using ARC, object variables are retained and released automatically as the block is copied and later released.
EDIT:
As to your concern with the Anti-patterns you mention, I think that in both anti-pattern examples, the critical point is the the variable declaration and the "block literal" assigned to it have different scope. Take the for case presented there:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: The block literal scope is the "for" loop
}
}
blockArray is visible within the whole method body;
in the for loop, you create a block; a block is an object (some storage in memory) and has an address; the block as an object has "stack-local data structure" (from the reference above), i.e., it is allocated on the stack when you enter the method;
the fact that the "block literal" is treated as a variable local to the for loop, means that that storage can be reused at each successive iteration;
the block addresses are assigned to blockArray elements;
when you exit the for loop, blockArray will contain addresses of blocks that are possibly not there anymore and/or have been overwritten at each step depending on what the compiler does to stack data structure created within a for scope.
Your case is different, since your local variable is also within the for scope, and it will not be visible outside of it.
The case presented as an anti-pattern is similar to this:
{
int array[3];
for (int i = 0; i < 3; ++i) {
int a = i;
array[i] = &a;
// WRONG: The block literal scope is the "for" loop
}
Very likely, the a variable within the for scope will be allocated on stack just once and then reused at each iteration of the loop. In principle, a (one copy) will be still there (I am not sure, actually, the C standard should be inspected) outside of the loop, but it is pretty clear that the meaning of that code is not really sensible.
OLD ANSWER:
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope.
I think this can be better understood like this: the lexical scope of the __block variable and all blocks (as per above definition) will share the same storage for that variable. So, if one block (or the original lexical scope) modifies the variable (I mean here the variable pointing to the object), that change will be visible to all others.
Given this, one effect of declaring a variable as __block is that in the non-ARC case the object pointed-to by it will not be automatically retained by each block where it is passed into (with ARC, the retain is done also for __block variables).
Both when using ARC and not using ARC, you need to use the __block specifier when you want to change the variable value and want that all blocks use the new value. Imagine that you had a block to initialize your _myLayers ivar: in this case, you would need to pass the _myLayers variable into the block as a __block variable, so that it (vs. a copy of it) can be modified.
In your case, if you are not using ARC, then, it all depends on whether the object pointed to by layer will be still there when the block is executed. Since layer comes from _myLayers, this converts into whether the object owning _myLayers will be still there when the block is executed. The answer to this is normally yes, since the block we are talking about is the completion block for an animation on that layer. (It would have been different, say, if it were the completion block for a network request).
Hope this helps.

Objective C: Initializing static variable with static method call

The Compiler claims an error saying: "initializer element is not constant", when I try to initialize a static variable inside a method with a call to a static method (with + in its definition).
Anyway I can tell him that this method always returns the same value. I know this is not the same as static method, but there seems to be no constant methods in Objective-C (other than macros which won't work here because I am calling UI_USER_INTERFACE_IDIOM() from inside the method).
There's actually another solution in addition to Yuji's. You can create a function and prefix it with a GCC attribute (also works in Clang and LLVM) that will cause it to be executed before main() is. I've used this approach several times, and it looks something like this:
static NSString *foo;
__attribute__((constructor)) initializeFoo() {
foo = ...;
}
When you actually use foo, it will already be initialized. This mean you don't have to check whether it's nil each time. (This is certainly a minor performance benefit, though multiplied by the number of times you use it, but it can also simplify one or more other regions of code. For example, if you reference the static variable in N different places, you might have to check for nil in all N or risk a crash. Often, people call a function or use a #define to handle initialization, and if that code is only actually used once, it can be a penalty worth removing.
You cannot do that in Objective-C.
There are two solutions:
Switch to Objective-C++. Change the file extension from .m to .mm.
Initialize it with nil, and check it when you first use it, as in:
static NSString*foo=nil;
if(!foo){
foo=[ ... ] ;
}