专注、坚持

Objective-C 与 Swift 桥接中的坑

2019.01.17 by kingcos
Date Notes
2019-01-17 添加「Optional 与 Nullability」
添加「NSNotificationNameNotification.Name

Preface

Objective-C 与 Swift 的混编是全面转向 Swift 中的必经之路,本文即是这一过程中的踩坑「真实」记录。

Optional 与 Nullability

  • Swift 4.2

在大多数项目中,我们都是在中途决定转向 Swift,Swift 中比较核心且常见的概念便是 Optional,可选类型,而这与 Obj-C 中的概念不大相同。在 Swift 中使用 Obj-C 桥接的属性(特别是 Block)时,尤其要注意:Obj-C 默认属性将被转换为隐式解包类型(SomeClass!),而在 Swift 中这代表开发者要保证值不为 nil,编译器将不再提示。当属性是 Block 时,若直接调用了为 nil 的 Closure 时,将会出现崩溃。

Obj-C Usage Swift
nullable 可空 SomeClass?
nonnull 不可空 SomeClass
null_unspecified 未指定是否可空(默认 SomeClass!

NSNotificationName 与 Notification.Name

  • Swift 4.2

Swift 诞生即看重安全,而硬编码是代码中很难去保证安全性的一环。Swift 4.2 中的 Notification.Name 即通知名更改为更加安全的做法,而为了和 Obj-C 中的 NSNotificationName 可以兼容,需要在 Obj-C 中的声明后增加 NS_EXTENSIBLE_STRING_ENUM 宏。

  1. 在增加了 NS_EXTENSIBLE_STRING_ENUM 宏后,Swift 中可以使用类似枚举的语法;
  2. 为了 Swift 更简单的语法,如果类型名位于变量名开头,则需要在 Swift 中会忽略并以首字母小写形式使用,eg. NSNotificationNameDidUpdate -> .didUpdate
  3. 对于NSNotificationName,Obj-C 变量结尾含有 Notification,也会进行忽略,经过测试此条并不适用其他声明 NS_EXTENSIBLE_STRING_ENUM 的自定义类型,eg. DidUpdateNotification -> .DidUpdate
  4. 当同时满足 2 & 3,则会优先 3,eg. NSNotificationNameDidUpdateNotification -> .NSNotificationNameDidUpdate
  5. 需要注意因此可能会存在通知重叠的可能,eg. DidUpdateNotification & DidUpdate 在 Swift 中均为 .DidUpdate => Ambiguous use of ‘DidUpdate’。