77

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;

Screenshot

Why this warning is showing and how should I fix it?

Jayprakash Dubey
  • 35,723
  • 18
  • 170
  • 177
kelin
  • 11,323
  • 6
  • 67
  • 104
  • If you wish to actually disable the warning all together instead of just conforming your coding style to it, then see here: https://stackoverflow.com/a/57122456/2057171 – Albert Renshaw Jan 21 '21 at 07:43

6 Answers6

74

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* why do we have to do this? 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 objects that wrap up either the object or nil).

Kevin
  • 1,883
  • 16
  • 23
  • Again, I think you should have explained why you have to use the macros around the blocs of declaration??? – Randika Vishman Nov 21 '16 at 06:13
  • Plus 1. I had one .h file that was missing the annotations, and I got the error only on my first @property. This pointed me in the right direction. – Jeff Oct 25 '22 at 05:13
64

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

Ares
  • 5,905
  • 3
  • 35
  • 51
  • I must add that compiler is also points to specify something for the block parameters. – kelin Sep 12 '15 at 22:34
  • 1
    Are you asking why you need to specify them at all? Because of the interoperability with the Swift compiler. It determines whether the API is exposed as an optional or not. See the Apple Blog post here: https://developer.apple.com/swift/blog/?id=25 – bandejapaisa Jan 16 '17 at 14:22
  • 2
    I second mskw reaction as well. Like why all of a sudden this is needed. Plus I am coding in ObjC so this has nothing to do with Swift crap. – GeneCode Feb 05 '17 at 05:58
  • 2
    @bandejapaisa Re: why… I'd say it's because Apple wants you to make you explicitly opt in to Tony Hoare's "billion dollar mistake." https://www.linkedin.com/pulse/20141126171912-7082046-tony-hoare-invention-of-the-null-reference-a-billion-dollar-mistake – clozach Mar 06 '17 at 21:30
  • @David天宇Wong I edited the answer to satisfy your "why". – Ares Oct 18 '17 at 03:53
  • This made sense to me at first, because I do use both Swift and Obj-C (started as Obj-C and I've been much happier programming in Swift since). But what I'm not understanding is why I need this in files that are not included in the LawnGuru-Bridging header? I get if a function could potentially be used by Swift code it should be marked _nullable _nonnull so Swift knows which are and aren't optionals... but why does a file that is not called by Swift code need to adhere to this as well? Does my entire Objc-C portion of my project need these made explicit? – Jake T. Jul 10 '18 at 19:06
19

To disable this warning across your entire project

  1. Go to Build Settings

  2. Make sure you are viewing the "All" tab not "Basic" or "Customized"

  3. Search for the field Other Warning Flags.

  4. Add the following flag: -Wno-nullability-completeness.

  5. Now clean and build (⇧⌘K then ⌘R)

  6. 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.

  1. (2022 Edit), Double check that the warning flag setting persisted, for some reason the latest xCode often seems to not save this setting when I set it.
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
  • 3
    for Xcode 11 it seems to be `-Wno-nonnull` instead of `-Wno-nullability-completeness` – budiDino Oct 03 '19 at 05:53
  • 1
    @budidino For me it's still `-Wno-nullability-completeness` confirmed on xCode 11.4.1 – Albert Renshaw May 19 '20 at 04:07
  • 1
    This works on Xcode 11.5, just don’t skip the step 6. – Tricertops Jun 13 '20 at 13:30
  • Disabling this warning won't cause any issue? ¯\_(ツ)_/¯ – Jayprakash Dubey Jan 21 '21 at 06:00
  • 1
    @JayprakashDubey Correct, it's just a warning. If your code is good there will be no issue. But if you have something that needs to behave non-null and you pass null to it you yourself could encounter issues but that would be the case whether or not you had this warning disabled. This warning is to just help you prevent that, but if you know what you're doing then you can disable it, as it's a non-issue. – Albert Renshaw Jan 21 '21 at 07:42
14

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;
kelin
  • 11,323
  • 6
  • 67
  • 104
11

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.

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
fishtrees
  • 231
  • 3
  • 6
3

Remove below macro from your .h file and warning will disappear

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END
Dharman
  • 30,962
  • 25
  • 85
  • 135
dilip
  • 163
  • 8
  • Right. The simplest way to get around this warnings is to never anywhere in your code specify nullablility. – osxdirk Jun 23 '21 at 18:55