6

使用CLANG_ANALYZER_NONNULL(ie -Xclang nullability),我得到“从预期返回非空值的函数返回 Null ”:

在此处输入图像描述

使用 Xcode 7.3 和 iOS 9.3 文档,我检查initWithFrame:并返回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 文档已更新,现在是: initWithFrame:文档

所以没有更多的冲突。

4

2 回答 2

3

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

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

于 2016-02-23T19:51:17.073 回答
1

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

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

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

从这个初始化器返回nonnull也是合乎逻辑的,因为 anUIView是一个抽象对象,它包含有关最终将在屏幕上呈现的内容的信息,它本身没有太多限制。

同样,将 nil 字符串传递给没有太大意义,[NSURL URLWithString:]因为NSURL字符串具有明确定义的要求,而nilone 不满足它们,因此在nonnull此处添加注释是有意义的。

于 2016-02-22T18:22:36.707 回答