70

在 Xcode 7 GM 中,我开始收到此警告:

指针缺少可空性类型说明符(_Nonnull、_Nullable 或 _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;

截屏

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

4

6 回答 6

67

您可以在目标 c 标头中的声明块(函数和变量)周围使用以下宏:

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

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

如:

@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 类与 swift 可互操作,您需要声明可空性,以便编译器知道是否将属性视为 swift 选项。可空的目标 c 属性在 swift 中被称为可选项,并且将这些宏与可空的属性声明符结合使用允许编译器将它们视为可选项(可选项是 monad - 包装对象或 nil 的对象)。

于 2016-03-22T20:05:36.630 回答
64

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 允许可选参数 (?),而 Objective-C 不允许。这是作为两者之间的桥梁,以便 Swift 编译器知道这些参数是可选的。'Nonnull' 将告诉 Swift 编译器该参数是必需的。一个可空的,它是可选的

欲了解更多信息,请阅读: https ://developer.apple.com/swift/blog/?id=25

于 2015-09-12T17:00:47.213 回答
17

在整个项目中禁用此警告

  1. 转到构建设置

  2. 确保您查看的是“全部”选项卡,而不是“基本”或“自定义”

  3. 搜索字段Other Warning Flags

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

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

  6. 退出 Xcode 并重新打开它(不要跳过这一步!

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

于 2019-07-20T06:49:28.830 回答
14

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

- (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;
于 2015-09-14T15:45:12.680 回答
11

我发布此答案以说明为什么要添加_Nonnullor nullable

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

Swift 的一大优点是它可以透明地与 Objective-C 代码互操作,既有用 Objective-C 编写的现有框架,也有你的应用程序中的代码。但是,在 Swift 中,可选引用和非可选引用之间有很大的区别,例如NSViewvs. NSView?,而 Objective-C 将这两种类型都表示为NSView *. 因为 Swift 编译器不能确定一个特定的是否NSView *是可选的,所以这个类型被引入 Swift 作为一个隐式展开的可选,NSView!.

这一切都是为了斯威夫特。

于 2016-08-16T03:14:46.800 回答
1

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

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END
于 2019-09-19T07:24:30.427 回答