Clang可空性警告以及如何处理它们

时间:2016-03-29 18:35:29

标签: ios objective-c xcode objective-c-nullability

最近我在Xcode中打开了CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION,我的Objective-C代码中出现了与可空性相关的警告。最常见的一种警告类型是Implicit conversion from nullable pointer 'TypeA * _Nullable' to non-nullable pointer type 'TypeA * _Nonnull'

我开始尝试通过在这里描述的方法中创建相同类型的本地来删除这些警告。 https://www.mail-archive.com/xcode-users%40lists.apple.com/msg02260.html 本文首先使用local来说,该对象的属性是未指定的可空的,因此它可以作为期望非空的方法的合法参数。

但我觉得这是一个警察行动,并没有以任何有益的方式解决问题。

有没有人经历过这个练习?如果你能分享你所采取的策略,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

实际上,我已经把这个话题搞砸了一下。我想在一个有点大的项目中改善可空性状况(让它更“快捷”)。这是我发现的。

首先,您应该启用CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION-Wnullable-to-nonnull-conversion

其次,关于

  

首先使用本地,该对象的属性未指定为可空,   所以它可以作为期望非空的方法的合法参数。

这闻起来很糟糕,我创建了一个名为NONNUL_CAST()的宏。以下是如何实现它的示例:

#define NONNUL_CAST(__var) ({ NSCAssert(__var, @"Variable is nil");\
    (__typeof(*(__var))* _Nonnull)__var; })

在这里你可以看到hacky __typeof(*(__var))* _Nonnull)__var,但它并不是那么糟糕。如果__var类型为A* _Nullable,我们会取消引用__var,因此在我们再次引用之后,它现在只是A,但是_Nonnull,并获得非空{ {1}}作为答案。当然,我们断言,万一出现问题。

第三,你必须在每个局部变量上指定nullabilty,你应该将所有代码放在__var中,如下所示:

NS_ASSUME_NONNULL_BEGIN/END

您在NS_ASSUME_NONNULL_BEGIN <your_code_goes_here> NS_ASSUME_NONNULL_END` .h文件中放置了 EVERY LINE (导入除外)代码。这将假设所有方法,返回类型和属性的参数都是非空的。如果你想让它可以为空,可以在那里设置可空。

所以,一切都完成了,现在是什么? 以下是典型用法示例:

.m

现在你有更强大的可控性。可能是看起来不太好,但它是客观的,所以没什么可抱怨的。

答案 1 :(得分:0)

并非每一个警告都有意义。有时它在编译器中是一个缺点。例如,此代码不需要警告。

- (nullable id)transformedValue:(nullable id)value {
    id result = value != nil ? UIImageJPEGRepresentation(value, 1.0) : nil;
    return result;
}

我们正在检查它是否为空!我们还能做什么?为什么要创建额外的指针?

所以,我们这样做:

- (nullable id)transformedValue:(nullable id)value {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion"
    id result = value != nil ? UIImageJPEGRepresentation(value, 1.0) : nil;
#pragma clang diagnostic pop
    return result;
}

为什么这是正确的答案?

首先,它比编译器更聪明。您不想因为虚假警告而开始破坏您的代码。

此解决方案指定要抑制的确切警告消息,并且仅针对一行禁止它。