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

uqcuzwp8  于 2022-12-27  发布在  iOS
关注(0)|答案(6)|浏览(128)

在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;

为什么显示此警告以及如何修复?

0yycz8jy

0yycz8jy1#

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

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

然后,你需要为在该块中可以为空的引用添加可空注解,这适用于函数参数和变量声明。
例如:

@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中被称为可选项,使用这些宏与属性的可空声明符一起允许编译器把它们当作可选项(可选对象是指 Package object或nil的对象)。

gzszwxb4

gzszwxb42#

您还需要为处理程序/块指定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编译器在两者之间建立的桥梁,让Swift编译器知道这些参数是可选的。"Nonnull“将告诉Swift编译器该参数是必需的。”nullable“将告诉Swift编译器该参数是可选的
有关详细信息,请阅读:https://developer.apple.com/swift/blog/?id=25

o2rvlv0m

o2rvlv0m3#

在整个项目中禁用此警告

1.转到生成设置
1.确保您查看的是"全部"选项卡,而不是"基本"或"自定义"选项卡
1.搜索字段 * 其他警告标志 *。
1.添加以下标志:-Wno-nullability-completeness.
1.现在清理并构建(K然后R)
1.退出Xcode并重新打开它(不要跳过此步骤!

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

1.(2022年编辑),仔细检查警告标志设置是否持续存在,由于某种原因,最新的xCode似乎经常在我设置它时不保存此设置。

fgw7neuy

fgw7neuy4#

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

- (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;
xe55xuns

xe55xuns5#

我发布这个答案是为了告诉你为什么要添加_Nonnullnullable
根据这个博客:https://developer.apple.com/swift/blog/?id=25
Swift的一个优点是它可以透明地与Objective-C代码进行互操作,无论是用Objective-C编写的现有框架还是应用程序中的代码。然而,在Swift中,可选引用和非可选引用之间有很大的区别,例如NSViewNSView?。而Objective-C将这两种类型都表示为NSView *,因为Swift编译器无法确定某个NSView *是否可选,该类型作为隐式展开的可选项NSView!被引入Swift。
"都是为了斯威夫特"

6rqinv9w

6rqinv9w6#

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

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

相关问题