Pointer is missing a nullability type specifier
IosObjective CObjective C-NullabilityIos Problem Overview
In Xcode 7 GM I started to get this warning:
> Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)
In the following function declaration (NSUserDefaults extension)
- (void)setObject:(nullable id)value
forKey:(NSString *)defaultName
objectChanged:(void(^)(NSUserDefaults *userDefaults, id value))changeHandler
objectRamains:(void(^)(NSUserDefaults *userDefaults, id value))remainHandler;
Why this warning is showing and how should I fix it?
Ios Solutions
Solution 1 - Ios
You can use the following macros around blocks of declarations (functions and variables) in objective c headers:
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
You need to then add nullable annotations for references that can be nil within that block. This applies to both function parameters and variable declarations.
As in:
@interface SMLBaseUserDetailsVC : UIViewController < UICollectionViewDelegate>
NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) IBOutlet UIScrollView *detailsScrollView;
@property (nonatomic, readonly) IBOutlet UICollectionView *photoCV;
@property (nonatomic, weak, readonly) SMLUser *user;
- (IBAction)flagUser:(id)sender;
- (IBAction)closeAction:(nullable id)sender;
- (void) prefetchPhotos;
NS_ASSUME_NONNULL_END
@end
Edit* The why??? is because for an objective-c class to be interoperable with swift, you need to declare nullability so that the compiler knows to treat properties as swift optionals or not. Nullable objective c properties are known as optionals in swift and using these macros in conjunction with the nullable declarators for properties allows the compiler to treat them as optionals (Optionals are monads - an object that wraps up either the object or nil).
Solution 2 - Ios
You need to specify nullable
also for the handlers/blocks
- (void)setObject:(nullable id)value
forKey:(nonnull NSString *)defaultName
objectChanged:(nullable void(^)(NSUserDefaults *userDefaults, id value))changeHandler
objectRamains:(nullable void(^)(NSUserDefaults *userDefaults, id value))remainHandler;
Why? It's due to Swift. Swift allows optional parameters (?), which Objective-C does not. This is done as a bridge between the both of them for the Swift compiler to know those parameters are optional. A 'Nonnull' will tell the Swift compiler that the argument is the required. A nullable that it is optional
For more info read: https://developer.apple.com/swift/blog/?id=25
Solution 3 - Ios
To disable this warning across your entire project
-
Go to Build Settings
-
Make sure you are viewing the "All" tab not "Basic" or "Customized"
-
Search for the field Other Warning Flags.
-
Add the following flag:
-Wno-nullability-completeness
. -
Now clean and build (⇧⌘K then ⌘R)
-
Quit Xcode and re-open it (Don't skip this step!)
Note: It can take a few seconds for the warnings to go away even after you finish building and relaunching Xcode, for me it takes about 15 seconds for Xcode to fully update.
Solution 4 - Ios
The correct, working method declaration, accepted by compiler:
- (void)setObject:(nullable id)value
forKey:(nonnull NSString *)defaultName
objectChanged:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))changeHandler
objectRamains:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))remainHandler;
Solution 5 - Ios
I post this answer to tell why should add _Nonnull
or nullable
.
According to this blog: https://developer.apple.com/swift/blog/?id=25
> One of the great things about Swift is that it transparently interoperates with Objective-C code, both existing frameworks written in Objective-C and code in your app. However, in Swift there’s a strong distinction between optional and non-optional references, e.g. NSView
vs. NSView?
, while Objective-C represents boths of these two types as NSView *
. Because the Swift compiler can’t be sure whether a particular NSView *
is optional or not, the type is brought into Swift as an implicitly unwrapped optional, NSView!
.
it's all for Swift.
Solution 6 - Ios
Remove below macro from your .h file and warning will disappear
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END