Using CLANG_ANALYZER_NONNULL
(i.e. -Xclang nullability
), I got "Null is returned from a function that is expected to return a non-null value":
Using Xcode 7.3 and iOS 9.3 documentation, I checked initWithFrame:
and it can return nil
:
But UIView.h encapsulates everything with NS_ASSUME_NONNULL_BEGIN
, so we can interpret the following:
as:
- (nonnull instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
So documentation explains it's nullable
, while header file says it's nonnull
. Which one to trust?
Should I write:
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) {
// workaround for clang analyzer
return (void * _Nonnull)nil;
}
// Initialization code
return self;
}
Or:
- (nonnull instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
// Initialization code
return self;
}
🔴🔴🔴
Xcode documentation was updated and is now:
So no more conflict.
In the case of UIView
's -initWithFrame
initializer, the recommendation is to not defensively check the result of calling the super initializer because there is realistically nothing an application can do to recover from a failed UIView
allocation.
Also, as of Xcode 7.3 beta 4, the static analyzer no longer warns here. It now doesn't warn about returning nil from the -init
, -copy
, and -mutableCopy
families even when these methods have a return type with a nonnull
type qualifier to avoid warning on exactly this common defensive idiom.
The headers usually take precedence, as many times the documentation is either left behind or overlooked. UIKit
(among the other CocoaTouch
frameworks) headers are more up-to-date than the documentation for another reason: better Swift
interoperability.
So you should go with the second approach:
- (nonnull instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
// Initialization code
return self;
}
Returning nonnull
from this initializer is also logical, as an UIView
is an abstract object that holds information about something that will eventually be rendered on the screen, it doesn't have many restrictions on it own.
Similarly, it doesn't make much sense to pass a nil string to [NSURL URLWithString:]
as NSURL
strings have clearly defined requirements, and a nil
one doesn't satisfy them, so it makes sense to have the nonnull
annotation here.
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