指针缺少可空性类型说明符

Pointer is missing a nullability type specifier

在 Xcode 7 GM 我开始收到这个警告:

Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)

在下面的函数声明中(NSUserDefaults 扩展)

- (void)setObject:(nullable id)value
           forKey:(NSString *)defaultName
    objectChanged:(void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

为什么显示此警告,我应该如何解决?

您还需要为 handlers/blocks

指定 nullable
- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

为什么?这是由于 Swift。 Swift 允许可选参数 (?),而 Objective-C 不允许。这是作为两者之间的桥梁,让 Swift 编译器知道这些参数是可选的。 'Nonnull' 将告诉 Swift 编译器该参数是必需的。可选的可空值

有关详细信息,请阅读: https://developer.apple.com/swift/blog/?id=25

编译器接受的正确的工作方法声明:

- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))remainHandler;

您可以在 objective c headers 中围绕声明块(函数和变量)使用以下宏:

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

然后您需要为该块中可以为 nil 的引用添加可为 null 的注释。这适用于函数参数和变量声明。

如:

@interface SMLBaseUserDetailsVC : UIViewController < UICollectionViewDelegate>
NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, readonly) IBOutlet UIScrollView *detailsScrollView;
@property (nonatomic, readonly) IBOutlet UICollectionView *photoCV;
@property (nonatomic, weak, readonly) SMLUser *user;
- (IBAction)flagUser:(id)sender;
- (IBAction)closeAction:(nullable id)sender;
- (void) prefetchPhotos;

NS_ASSUME_NONNULL_END

@end

编辑* 为什么???是因为要使 objective-c class 与 swift 互操作,您需要声明可空性,以便编译器知道是否将属性视为 swift 可选项。可空 objective c 属性在 swift 中被称为可选值,并且将这些宏与属性的可为空声明符结合使用允许编译器将它们视为可选值(可选值是 monad - 一个 object 包装向上 object 或 nil).

我post这个答案告诉为什么要加_Nonnullnullable.

根据此博客:https://developer.apple.com/swift/blog/?id=25

One of the great things about Swift is that it transparently interoperates with Objective-C code, both existing frameworks written in Objective-C and code in your app. However, in Swift there’s a strong distinction between optional and non-optional references, e.g. NSView vs. NSView?, while Objective-C represents boths of these two types as NSView *. Because the Swift compiler can’t be sure whether a particular NSView * is optional or not, the type is brought into Swift as an implicitly unwrapped optional, NSView!.

都是为了Swift。

在整个项目中禁用此警告

  1. 转到构建设置

  2. 确保您查看的是 "All" 选项卡,而不是 "Basic" 或 "Customized"

  3. 搜索字段其他警告标志

  4. 添加以下标志:-Wno-nullability-completeness

  5. 现在清理并构建(⇧⌘K 然后 ⌘R)

  6. 退出Xcode并re-open它(不要跳过这一步!

    注意:即使您完成构建并重新启动 Xcode,警告也可能需要几秒钟才会消失,对我来说 Xcode 大约需要 15 秒全面更新。

从您的 .h 文件中删除以下宏,警告将会消失

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END