Swift 5.1: как я могу передать NULL в качестве аргумента? - PullRequest
2 голосов
/ 05 февраля 2020

Я пытаюсь установить наблюдателя для CFNotificationCenter.

В документации указано:

name

Имя уведомление для наблюдения. Если NULL, обратный вызов вызывается для любого уведомления, отправленного объектом. Если центр является центром уведомлений Дарвина, это значение не должно быть ПУСТО (NULL).

Насколько я понимаю, NULL не существует в Swift. Так какой же должен быть этот аргумент?

Следующее компилируется нормально, но пустая строка не NULL:

CFNotificationCenterAddObserver(
    CFNotificationCenterGetDistributedCenter(),
    UnsafeMutableRawPointer?.none,
    receiveNotification,
    "" as CFString,
    UnsafeRawPointer?.none,
    CFNotificationSuspensionBehavior.deliverImmediately
)

Я пробовал CFString?, NSNull и NSNull as String но компилятор жалуется.

Я неправильно понял документацию? Как указать значение NULL для имени параметра?

1 Ответ

4 голосов
/ 05 февраля 2020

Краткий ответ: Обнуляемые указатели из (Objective -) C являются необязательными указателями в Swift, и вы можете передать nil (иначе Optional.none) для имени для вызова любого уведомления, отправленного объектом.

Некоторый фон: Объявление этой функции C имеет вид

CF_EXPORT void CFNotificationCenterAddObserver(CFNotificationCenterRef center,
               const void *observer,
               CFNotificationCallback callBack, 
               CFStringRef name,
               const void *object,
               CFNotificationSuspensionBehavior suspensionBehavior);

, где тип параметр name является указателем, объявленным как

typedef const struct CF_BRIDGED_TYPE(NSString) __CFString * CFStringRef;

В документации (Objective- C) явно указано, что name может быть NULL, но, очевидно, объявление функции имеет не проверен на обнуляемость, , и поэтому параметр объявлен как неявный необязательный необязательный

_ name: CFString!

в Swift.

См. Обнуляемость и цель - C в блоге Swift и SE-0055. Явно обнуляйте небезопасные указатели, используя Optional для получения дополнительной информации об обнуляемости и как (Objective -) C указатели импортируются в Swift.

Так name: CFString! только говорит нам что компилятор Swift не знает, может ли параметр Objective- C быть NULL или нет, в противном случае он ведет себя как обычный необязательный CFString?, и вы можете передать значение nil, которое соответствует нулевому указателю NULL in (Цель -) C.

Аналогично, const void *object импортируется в Swift как _ object: UnsafeRawPointer!, потому что нет аннотации обнуляемости, и вы можете передать nil здесь (что вы уже делаете в явная форма UnsafeRawPointer?.none).

...