【问题标题】:Should an IBOutlet property be marked nullable or nonnull?应该将 IBOutlet 属性标记为可为空还是非空?
【发布时间】:2016-07-28 18:45:38
【问题描述】:

在 Objective-C 中,我习惯于声明连接到 Interface Builder 的属性

@property (nonatomic, weak) IBOutlet UIView *myView; 

现在我有一个使用新的 XCode 可空性属性的类。为了保持与 Swift 的兼容性,IBOutlet 应该具有什么可空性属性?根据苹果的“Using Swift with Cocoa and Objective-C”:

当你在 Swift 中声明一个出口时,你应该将出口的类型设为隐式展开的可选。这样,您可以在初始化后让情节提要在运行时连接插座。当你的类从故事板或 xib 文件初始化时,你可以假设插座已连接。

那么这是否意味着插座应该在 Objective-C 中声明为nonnull?

【问题讨论】:

  • 没有可空性注释的属性将作为隐式展开的选项导入。将其设为nonnull 会将其作为非可选项导入。你的IBOutlets 无论如何都应该在你的 .m 文件中声明,所以你用什么注释它并不重要。

标签: ios objective-c xcode cocoa-touch nullable


【解决方案1】:

如果您的类是用 Swift 编写的,则不能使用非可选属性,否则编译器会抱怨该属性从未初始化。这就是为什么 Apple 建议将其声明为隐式展开的可选项,因为一旦你的对象被初始化,你肯定知道该属性包含一个值(除非你有一个悬空的插座,顺便说一下……)

从 Objective-C 导出时,您可以将其标记为 nonnull,它会在 Swift 中作为非可选属性出现,在这种情况下很好。请注意,您不能同时使用nonnull 和weak。

所以你可以这样做:

@property (nonatomic, strong, nonnull) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet var subview: UIView

或

@property (nonatomic, weak, nullable) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet weak var subview: UIView?

如果出于某种原因,您仍希望将属性作为隐式解包选项导出到 Swift,则可以将该属性标记为 null_resettable 或 null_unspecified。这并不是它们的真正含义,但它仍然会产生预期的结果。有关这些注释的更多信息,请参阅this blog post。

@property (nonatomic, weak, null_unspecified) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet weak var subview: UIView!

【讨论】:

  • Swift 在没有错误的情况下崩溃了,不知道为什么,谢谢!
【解决方案2】:

weak 的声明意味着该属性可以为空。因此这是可行的

@property (nonatomic, weak, nullable) IBOutlet UIView *contentView;

声明属性nonnull 会出错。

【讨论】:

  • weak 隐含nullable,因此如果您的声明包含NS_ASSUME_NONNULL_BEGIN 和NS_ASSUME_NONNULL_END,则可以省略nullable。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 2018-08-06
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多