CoreBluetooth 中未记录的 API 更改
Undocumented API changes in CoreBluetooth
在Xcode 12.3中,CoreBluetooth.CBService.peripheral
在objective-c中定义为:
@property(assign, readonly, nonatomic) CBPeripheral *peripheral;
更新:这是 swift 在 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 以来一直存在,并且没有任何变化。但是在 Xcode13 中,变量显然是可选的。 (并且它在 Xcode 12.3 中不是可选的,因为它缺少属性 nullable
。)
修复相对容易(例如 service.peripheral -> service?.peripheral
)- 但它使得无法对 Xcode 12.3 和 13.0 使用相同的代码。我想知道这里是否有我遗漏的细微差别?
可选项是 Swift 的固有部分,而不是 Objective-C 的一部分。 Swift 中的非空引用保证有一个值,而 Objective C 中的任何引用在理论上可以是 null
.
引入了 nullable
和 nonnull
装饰器以提高与 Swift 的互操作性,副作用是它们也更清楚地记录了 Objective C APIs .
Core Bluetooth 是 Objective C API,正如您所注意到的,它自 iOS5 以来就可用;在 Swift 和 nullable
装饰器之前。
因此,API 并没有发生太大变化,而是您将 Objective C API 与 Swift [=64= 进行比较] 并且 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
在Xcode 12.3中,CoreBluetooth.CBService.peripheral
在objective-c中定义为:
@property(assign, readonly, nonatomic) CBPeripheral *peripheral;
更新:这是 swift 在 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 以来一直存在,并且没有任何变化。但是在 Xcode13 中,变量显然是可选的。 (并且它在 Xcode 12.3 中不是可选的,因为它缺少属性 nullable
。)
修复相对容易(例如 service.peripheral -> service?.peripheral
)- 但它使得无法对 Xcode 12.3 和 13.0 使用相同的代码。我想知道这里是否有我遗漏的细微差别?
可选项是 Swift 的固有部分,而不是 Objective-C 的一部分。 Swift 中的非空引用保证有一个值,而 Objective C 中的任何引用在理论上可以是 null
.
引入了 nullable
和 nonnull
装饰器以提高与 Swift 的互操作性,副作用是它们也更清楚地记录了 Objective C APIs .
Core Bluetooth 是 Objective C API,正如您所注意到的,它自 iOS5 以来就可用;在 Swift 和 nullable
装饰器之前。
因此,API 并没有发生太大变化,而是您将 Objective C API 与 Swift [=64= 进行比较] 并且 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