Pregunta

When casting around (no pun intended) to clarify when to use __strong in a variable declaration I came across these lines in the Transitioning to ARC Release Notes:

You should decorate variables correctly. When using qualifiers in an object variable declaration, the correct format is:

  ClassName * qualifier variableName;

for example:

  MyClass * __weak myWeakReference;    
  MyClass * __unsafe_unretained myUnsafeReference;

Other variants are technically incorrect but are “forgiven” by the compiler. To understand the issue, see http://cdecl.org/.

I suspect this is some sort of in-joke on Apple’s part, but I don’t suppose I get it. It clearly doesn’t matter but I would like to do it right. What is the importance of correctly “decorating” a variable declaration, and what point is cdecl.org trying to make?

Edit: to clarify, I want to understand precisely why writing

qualifier ClassName * variableName;

is "technically incorrect."

¿Fue útil?

Solución

So I think I have an answer, but I can’t be sure if I’m correct. Feel free to provide a better one, or comment/upvote if you think I’ve nailed it.

CDecl is a C program which you can download from that same website. It exists to solve problems such as in this question.

Variable declarations in C can be pretty notorious, especially when typedefs are taken into account. There is a good introduction to this over at Unixwiz.net. You’ll find there a helpful introduction that will allow you to read even such monsters as char *(*(**foo [][8])())[]; (foo is array of array of 8 pointer to pointer to function returning pointer to array of pointer to char).

The rule with these is effectively proximity. Consider the simple example

const int * foo

This declares foo as a pointer to a constant int. However,

int * const foo

will declare foo as a constant pointer to an int. The subtle difference is discussed thoroughly in this question. (essentially, in the first example you can make foo point to another constant int, but cannot modify the constant int through foo; in the second, you can modify the int which foo points to, but you can’t make foo point to any other location in memory).

With these ARC attributes, the syntax of using

__strong NSString * myString

would declare myView as a pointer to a “strong” UIView. This is nonsensical. Only pointers to objects can have the attribute of being strong (or weak or whatever) under ARC. Therefore it is good practice to write

NSString * __strong myString

since this is in line with other C keywords.

I did ask myself: what happens under ARC if you declare a strong object pointer to a weak object pointer to, say, an NSString, like so

NSString * __weak * __strong myContrivedPointer;

but the same applies. Nothing but an object pointer can have these keywords. Consequently, it is nonsensical to declare a pointer to a pointer “strong”.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top