As an experiment I tried turning on the new “misuse of ’nonnull'” warning in Xcode 7.3, and got a ton of warnings. They all make sense, but assuming I were going to correct my code, I don’t know the best way go about it. For example, here’s a real warning reported in my project:
[hostArray addObject: url.host]; // Warning!
Here the problem is that NSURL.host returns a nullable NSString, but -[NSArray addObject:]’s parameter is not nullable.
One thing to note is that there are two build settings in Xcode 7.3 related to nullability:
- "Incorrect Uses of Nullable Values", a compiler warning, which is always *off* by default; and
- "Misuse of ’nonnull’", a static analyzer warning, which is the one enabled by default for newly created projects starting in Xcode 7.3 beta 3.
It looks like your warning above is from the compiler warning.
When "Incorrect Uses of Nullable Values" is enabled, Xcode passes the "-Wnullable-to-nonnull-conversion" flag to the compiler. This flag warns when an _expression_ of _Nullable type is used where a _Nonnull type is expected. With this build setting, the compiler will warn on your first example:
[hostArray addObject: url.host]; // Warning: implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'id _Nonnull'
This warning can be quite noisy, which is why it is disabled by default. The recommended mechanism for suppressing the warning is to store the value into a local of the the same type but with unspecified nullability:
NSString *host = url.host;
[hostArray addObject:host];
This kind of suppression is useful when there is a high-level invariant that guarantees that the _Nullable value is not nil — for example when fetching an object from an NSDictionary that you know contains the key. As Sean McBride noted later in the thread, you can add an assert() if you want run-time checking of this invariant when assertions are enabled.
The "Misuse of ’nonnull’" build setting is for the static analyzer. The setting is disabled for existing projects but enabled by default for newly created projects. When enabled, the static analyzer (i.e., “Analyze" in the “Product" Menu) will warn when you use a value that is known to be nil in a place where a _Nonnull value is expected. The static analyzer will not warn for "[hostArray addObject: url.host];" because the analyzer doesn’t *know* that url.host is nil (just that it is nullable). But it will warn in the following case:
NSString *s = nil;
NSURL *url ="" URLWithString:s]; // Static analyzer warns here nil is passed to +URLWithString, which takes a _Nonnull argument.
The static analyzer warning is off by default for existing projects because it can produce a large number of warnings for large codebases. However, it has a much better ratio of true positives to false positives than the compiler setting so it is turned on for newly created projects. With the static analyzer you can suppress the warning with an assertion that the value is not nil.
Devin Coughlin
Apple Program Analysis Team