`[UIView initWithFrame:]` 的冲突文档:可空还是非空?

Conflicting documentation for `[UIView initWithFrame:]`: nullable or nonnull?

使用 CLANG_ANALYZER_NONNULL(即 -Xclang nullability),我得到了“Null is returned from a function that expected to return a non -空值":

使用 Xcode 7.3 和 iOS 9.3 文档,我检查了 initWithFrame: 它可以 return nil:

但是UIView.h用NS_ASSUME_NONNULL_BEGIN封装了所有东西,所以我们可以解读如下:

如:

- (nonnull instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;

所以文档解释它是 nullable,而头文件说它是 nonnull。相信哪一个?

我应该写:

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (!self) {
        // workaround for clang analyzer
        return (void * _Nonnull)nil;
    }
    // Initialization code
    return self;
}

或者:

- (nonnull instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    // Initialization code
    return self;
}

更新

Xcode 文档已更新,现在:

所以没有更多的冲突。

headers 通常优先,因为很多时候文档要么被遗忘要么被忽视。 UIKit(在其他 CocoaTouch 框架中)headers 比文档更多 up-to-date 另一个原因:更好的 Swift 互操作性。

所以你应该采用第二种方法:

- (nonnull instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    // Initialization code
    return self;
}

从这个初始化器返回 nonnull 也是合乎逻辑的,因为 UIView 是一个抽象 object,它包含有关最终将在屏幕上呈现的东西的信息,它不会它本身没有很多限制。

同样,将 nil 字符串传递给 [NSURL URLWithString:] 没有多大意义,因为 NSURL 字符串有明确定义的要求,而 nil 不能满足它们, 所以这里有 nonnull 注释是有意义的。

对于 UIView-initWithFrame 初始化程序,建议不要防御性地检查调用超级初始化程序的结果,因为实际上应用程序无法从UIView 分配失败。

此外,从 Xcode 7.3 beta 4 开始,静态分析器不再在此处发出警告。它现在不会警告来自 -init-copy-mutableCopy 系列的 returning nil,即使这些方法的 return 类型带有 nonnull 类型限定符以避免对这个常见的防御性习语发出警告。