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

kel*_*lin 59 objective-c ios objective-c-nullability

在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;
Run Code Online (Sandbox Code Playgroud)

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

Are*_*res 57

您还需要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;
Run Code Online (Sandbox Code Playgroud)

为什么?这是由于斯威夫特.Swift允许可选参数(?),而Objective-C则没有.这是作为两者之间的桥梁完成的,以便Swift编译器知道这些参数是可选的.'Nonnull'将告诉Swift编译器该参数是必需的.可以认为它是可选的

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

  • 我也是第二次mskw反应.就像为什么突然间需要它.另外我在ObjC编码所以这与Swift垃圾无关. (2认同)
  • @bandejapaisa Re:为什么......我会说这是因为Apple希望你让你明确选择Tony Hoare的"十亿美元的错误".https://www.linkedin.com/pulse/20141126171912-7082046-tony-hoare-invention-of-the-null-reference-a-billion-dollar-mistake (2认同)

Kev*_*vin 55

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

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END
Run Code Online (Sandbox Code Playgroud)

然后,您需要为该块中可能为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
Run Code Online (Sandbox Code Playgroud)

编辑*为什么??? 因为要使一个objective-c类与swift可互操作,你需要声明为空,以便编译器知道将属性视为swift选项.可空的目标c属性在swift中称为选项,并且将这些宏与属性的可空声明器一起使用允许编译器将它们视为选项(Optionals是monad - 包装对象或nil的对象).


Alb*_*haw 17

在整个项目中禁用此警告

  1. 转到构建设置

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

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

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

  5. 现在清理和构建(??K 然后 ?R)

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

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

  • 对于 Xcode 11,它似乎是“-Wno-nonnull”而不是“-Wno-nullability-completeness” (2认同)

kel*_*lin 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;
Run Code Online (Sandbox Code Playgroud)


fis*_*ees 9

我发布这个答案,告诉为什么要添加_Nonnullnullable.

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

关于Swift的一个好处是,它透明地与Objective-C代码互操作,既有Objective-C编写的现有框架,也有应用程序中的代码.但是,在Swift中,可选参数和非可选参考之间存在很大差异,例如NSViewvs. NSView?,而Objective-C表示这两种类型的两种类型NSView *.因为Swift编译器无法确定某个特定是否NSView *是可选的,所以该类型作为一个隐式解包的可选项被带入Swift NSView!.

对于斯威夫特来说都是如此.