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

引入了 nullablenonnull 装饰器以提高与 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 声明从未nullablenull 值始终是可能的。

添加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 更改的主要内容,如果未能解决你的问题,请参考以下文章

iOS 和 CoreBluetooth 需要低能耗吗?

CoreBluetooth 是不是实现直接测试模式?

CoreBluetooth:我可以订阅具有读写权限的特性吗?

CoreBluetooth - TouchID应用

API 27 中未显示本地通知

在 mac osx 10.13 CoreBluetooth 框架上的 CBPeripheralStateDisconnecting 状态之后,外设状态永远不会改变