#swift #objective-c #xcode #core-bluetooth
#swift #objective-c #xcode #ядро-bluetooth
Вопрос:
В 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 указано, что этот API существует с iOS5, и никаких изменений не было. Однако в Xcode 13 переменная явно является необязательной. (И это не является необязательным в Xcode 12.3, поскольку в нем отсутствует атрибут nullable
.)
Исправление относительно простое (например service.peripheral -> service?.peripheral
), но оно делает невозможным использование одного и того же кода как для Xcode 12.3, так и для 13.0. Мне интересно, есть ли здесь какой-то нюанс, который я упускаю?
Ответ №1:
Опции являются неотъемлемой частью Swift и не являются частью Objective-C. Ненулевая ссылка в Swift гарантированно имеет значение, в то время как любая ссылка в Objective C теоретически может иметь null
значение .
Декораторы nullable
и nonnull
были введены для улучшения взаимодействия со Swift с тем побочным эффектом, что они также более четко документируют API Objective C.
Core Bluetooth — это Objective C API, и, как вы заметили, он доступен с iOS5; Задолго до Swift и nullable
декоратора.
Итак, дело не столько в том, что API изменился, скорее вы сравниваете Objective C API с Swift API, а Apple не добавила nullable
декоратор в основной Bluetooth API.
Ни один из этих API не изменился; Объявление Swift для peripheral
on CBService
всегда было необязательным. Объявление Objective-C никогда не имело, nullable
но null
значение всегда было возможно.
Добавление nullable
не изменит поведение API, только его объявление в Objective C. Это потенциально может стать критическим изменением для кода Objective-C или, по крайней мере, может привести к сбою компиляции, поэтому у Apple нет причин изменять его, и есть веская причина не делать этого.
Обновить
Судя по вашему комментарию, действительно, похоже, что в объявлении Swift CBService.peripheral
from 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
Комментарии:
1. Спасибо за ваш подробный ответ! Мне удалось найти разницу. Xcode12.3
unowned(unsafe) open var peripheral: CBPeripheral { get }
и Xcode 13:weak var peripheral: CBPeripheral? { get }
— таким образом, objc, возможно, не изменился, но быстрое преобразование изменилось.2. С учетом этих различий, есть ли способ скомпилировать один и тот же код CoreBluetooth swift как для Xcode 12.3, так и для Xcode 13?