在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;
为什么要显示此警告以及我该如何解决?
答案 0 :(得分:53)
您还需要为处理程序/块
指定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
答案 1 :(得分:50)
您可以在目标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中称为选项,并且将这些宏与属性的可空声明符一起使用允许编译器将它们视为选项(Optionals是monad - 包装对象或nil的对象)。
答案 2 :(得分:14)
The correct, working method declaration, accepted by compiler:
- (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;
答案 3 :(得分:9)
我发布此回答以说明为什么要添加_Nonnull
或nullable
。
根据此博客:https://developer.apple.com/swift/blog/?id=25
Swift的一大优点是它透明地与Objective-C代码互操作,既有用Objective-C编写的现有框架,也有用于应用程序中的代码。但是,在Swift中,可选和非可选引用之间存在很大区别,例如:
NSView
与NSView?
相对,而Objective-C将这两种类型都表示为NSView *
。因为Swift编译器无法确定特定的NSView *
是否是可选的,所以该类型作为隐式解包的可选项NSView!
被带入Swift。
这一切都适用于Swift。
答案 4 :(得分:0)
转到构建设置
确保您查看的是“全部”标签,而不是“基本”标签或“自定义”标签
搜索字段Other Warning Flags
添加以下标志:-Wno-nullability-completeness
。
现在清理并构建(先按cmd + shift + k再按cmd + r)
-请注意,即使在构建完成后,警告也会消失几秒钟,对我来说,xCode完全更新大约需要15秒钟
答案 5 :(得分:0)
从.h文件中删除下面的宏,警告将消失
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END