Consider the following method
- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
With the new nonnull and nullable annotation keywords we can enrich it as follows:
- (void)methodWithArg:(nonnull NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
but we also get this warning:
Pointer is missing a nullability type specifier (__nonnull or __nullable)
It refers to the third parameter (the block one).
The documentation doesn't cover with examples how to specify the nullability of block parameters. It states verbatim
You can use the non-underscored forms nullable and nonnull immediately after an open parenthesis, as long as the type is a simple object or block pointer.
I tried putting one of the two keywords for the block (in any position) without any luck. Also tried the underscore prefixed variants (__nonnull and __nullable).
Therefore my question is: how can I specify the nullability semantic for block parameters?
This seems to be working
- (void)methodWithArg:(nonnull NSString *)arg1
andArg:(nullable NSString *)arg2 completionHandler:(nullable void (^)
(NSArray * _Nullable results, NSError * _Nonnull error))completionHandler
You need to specify nullability both for the block and its parameters...
EDIT: For more information, see Swift Blog
According to Apple Blog ("Nullability and Objective-C"), you can use
NS_ASSUME_NONNULL_BEGIN and NS_ASSUME_NONNULL_END.
Within these regions, any simple pointer type will be assumed to be nonnull. Then you can just add nullable for nullable object, which like
NS_ASSUME_NONNULL_BEGIN
@interface MyClass: NSObject
- (void)methodWithArg:(NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
@end
NS_ASSUME_NONNULL_END
NSError ** type, should be NSError * _Nullable * _Nullable
id * type, better use id _Nullable * _Nonnull, it depends (may be you want a _Nullable id * _Nullable type).NSObject * type, you need put annotation after pointer, like this NSObject * _Nullable * _Nonnull Note
_Nonnull and _Nullable should used after pointer or id (Apple does in the example code AAPLListItem * _Nullable), but the non-underscored forms nonnull and nullable can used after an open parenthesis.
However, in the common case there’s a much nicer way to write these annotations: within method declarations you can use the non-underscored forms
nullableandnonnullimmediately after an open parenthesis, as long as the type is a simple object or block pointer.
check more in "Nullability and Objective-C"
For safety, there are a few exceptions to this rule:
typedeftypes don’t usually have an inherent nullability—they can easily be either nullable or non-nullable depending on the context. Therefore,typedeftypes are not assumed to benonnull, even within audited regions.- More complex pointer types like
id *must be explicitly annotated. For example, to specify a non-nullable pointer to a nullable object reference, use_Nullable id * _Nonnull.- The particular type
NSError **is so often used to return errors via method parameters that it is always assumed to be a nullable pointer to a nullableNSErrorreference.
The _Nullable id * _Nonnull can be confused, id _Nullable * _Nonnull is better understanding.
_Nonnull and _Nullable should used after pointer or id (Apple does in the example code AAPLListItem * _Nullable)
You can also do like this:
- (id __nullable)methodWithArg:(NSString * __nullable)arg1
andArg:(NSString * __nonnull)arg2
completionHandler:(void (^ __nonnull)(NSArray * __nonnull results, NSError * __nullable error))completionHandler;
It only depends which syntax you like more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With