CoreBluetooth 中未记录的 API 更改
Posted
技术标签:
【中文标题】CoreBluetooth 中未记录的 API 更改【英文标题】:Undocumented API changes in CoreBluetooth 【发布时间】:2022-01-06 23:29:02 【问题描述】:在 Xcode 12.3 中,CoreBluetooth.CBService.peripheral
在 Objective-c 中定义为:
@property(assign, readonly, nonatomic) CBPeripheral *peripheral;
更新:这是在 Xcode 12.3 中对上述内容的快速翻译:
unowned(unsafe) open var peripheral: CBPeripheral get
在 Xcode 13.0 中,CBService.peripheral
在 swift 中定义为:
weak var peripheral: CBPeripheral? get
Apple's documentation 声明这个 API 从 ios5 开始就存在并且没有任何变化。但是在 Xcode 13 中,变量显然是可选的。 (并且它在 Xcode 12.3 中不是可选的,因为它缺少属性 nullable
。)
修复相对容易(例如service.peripheral -> service?.peripheral
) - 但它使得 Xcode 12.3 和 13.0 无法使用相同的代码。我想知道这里是否有一些我遗漏的细微差别?
【问题讨论】:
【参考方案1】:Optional 是 Swift 的固有部分,它们不是 Objective-C 的一部分。 Swift 中的非空引用保证有一个值,而 Objective C 中的任何引用理论上都可以是 null
。
引入了 nullable
和 nonnull
装饰器以提高与 Swift 的互操作性,其副作用是它们还可以更清晰地记录 Objective C API。
Core Bluetooth 是一个 Objective C API,正如您所注意到的,它从 iOS5 开始就可用;早于 Swift 和 nullable
装饰器。
因此,API 没有太大变化,而是您将 Objective C API 与 Swift API 进行比较,而 Apple 并未将 nullable
装饰器添加到 Core Bluetooth API。
这些 API 都没有改变; CBService
上的 peripheral
的 Swift 声明始终是可选的。 Objective-C 声明从未有 nullable
但null
值始终是可能的。
添加nullable
不会改变API 的行为,只会改变它在Objective C 中的声明。这可能是Objective-C 代码的重大更改,或者至少可能导致编译失败,所以没有Apple 改变它的理由和不改变它的充分理由。
更新
从您的评论来看,确实,CBService.peripheral
的 Swift 声明似乎发生了重大变化,从 unowned(unsafe)
变为弱可选。
这是一个更安全的声明,因为在之前的定义中,您有责任检查 peripheral
不是 nil
,否则可能会发生崩溃。
在我多年的 Core Bluetooth 编程中,我认为我从来不需要使用 CBService.peripheral
,但是,您可以使用基于 Swift 版本的条件编译来编写在 Xcode 13 和早期版本:
var p: CBPeripheral?
#if swift(<5.5)
if s.peripheral != nil
p = s.peripheral
#else
p = s.peripheral
#endif
【讨论】:
感谢您的详细解答!我设法找到了不同之处。 Xcode12.3 是unowned(unsafe) open var peripheral: CBPeripheral get
而 Xcode 13 是:weak var peripheral: CBPeripheral? get
- 所以 objc 可能没有改变,但快速转换确实发生了。
有了这些差异,有没有办法在 Xcode 12.3 和 Xcode 13 上编译相同的 CoreBluetooth swift 代码?以上是关于CoreBluetooth 中未记录的 API 更改的主要内容,如果未能解决你的问题,请参考以下文章
CoreBluetooth:我可以订阅具有读写权限的特性吗?
在 mac osx 10.13 CoreBluetooth 框架上的 CBPeripheralStateDisconnecting 状态之后,外设状态永远不会改变