With Xcode 6.3 there were new annotations introduced for better expressing the intention of API's in Objective-C (and to ensure better Swift support of course). Those annotations were of course nonnull
, nullable
and null_unspecified
.
But with Xcode 7, there is a lot of warnings appearing such as:
Pointer is missing a nullability type specifier (_Nonnull, _Nullable or _Null_unspecified).
In addition to that, Apple uses another type of nullability specifiers, marking their C code (source):
CFArrayRef __nonnull CFArrayCreate(
CFAllocatorRef __nullable allocator, const void * __nonnull * __nullable values, CFIndex numValues, const CFArrayCallBacks * __nullable callBacks);
So, to sum up, we now have these 3 different nullability annotations:
nonnull
,nullable
,null_unspecified
_Nonnull
,_Nullable
,_Null_unspecified
__nonnull
,__nullable
,__null_unspecified
Even though I know why and where to use which annotation, I'm getting slightly confused by which type of annotations should I use, where and why. This is what I could gather:
- For properties I should use
nonnull
,nullable
,null_unspecified
. - For method parameters I should use
nonnull
,nullable
,null_unspecified
. - For C methods I should use
__nonnull
,__nullable
,__null_unspecified
. - For other cases, such as double pointers I should use
_Nonnull
,_Nullable
,_Null_unspecified
.
But I'm still confused as to why we have so many annotations that basically do the same thing.
So my question is:
What is exact difference between those annotations, how to correctly place them and why?
Best Answer
From the
clang
documentation:, and
So for method returns and parameters you can use the the double-underscored versions
__nonnull
/__nullable
/__null_unspecified
instead of either the single-underscored ones, or instead of the non-underscored ones. The difference is that the single and double underscored ones need to be placed after the type definition, while the non-underscored ones need to be placed before the type definition.Thus, the following declarations are equivalent and are correct:
For parameters:
For properties:
Things however complicate when double pointers or blocks returning something different than void are involved, as the non-underscore ones are not allowed here:
Similar with methods that accept blocks as parameters, please note that the
nonnull
/nullable
qualifier applies to the block, and not its return type, thus the following are equivalent:If the block has a return value, then you're forced into one of the underscore versions:
As conclusion, you can use either ones, as long as the compiler can determine the item to assign the qualifier to.