使用CLANG_ANALYZER_NONNULL
(即-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文档已更新,现在是:
所以不再有冲突。
答案 0 :(得分:3)
对于UIView
的{{1}}初始化程序,建议不要在防御性方面检查调用超级初始化程序的结果,因为实际上没有任何应用程序可以从失败中恢复{ {1}}分配。
此外,从Xcode 7.3 beta 4开始,静态分析仪不再在此处发出警告。它现在不会警告从-initWithFrame
,UIView
和-init
系列返回nil,即使这些方法具有带-copy
类型限定符的返回类型以避免警告正是这种常见的防御习语。
答案 1 :(得分:1)
标题通常优先,因为很多时候文档要么被遗忘要么被忽略了。 UIKit
(在其他CocoaTouch
框架中)标题由于其他原因而比文档更新:更好Swift
互操作性。
所以你应该采用第二种方法:
- (nonnull instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
// Initialization code
return self;
}
从这个初始化程序返回nonnull
也是合乎逻辑的,因为UIView
是一个抽象对象,它包含最终将在屏幕上呈现的内容的信息,它没有很多限制就自己而言。
同样,将{0}字符串传递给[NSURL URLWithString:]
并没有多大意义,因为NSURL
字符串有明确定义的要求,nil
一个字符串没有满足它们,所以在这里使用nonnull
注释是有意义的。