Использование CFNotificationCallback в Swift или блоки @convention(c) в Swift

Я пытаюсь прослушать уведомления CoreTelephony с помощью (теперь закрытого) CTTelephonyCenterAddObserver С функция и CFNotificationCallback блоки обратного вызова.

Мой соединительный заголовок (для внешних функций C):

#include <CoreFoundation/CoreFoundation.h>

#if __cplusplus
extern "C" {
#endif

#pragma mark - API

    /* This API is a mimic of CFNotificationCenter. */

    CFNotificationCenterRef CTTelephonyCenterGetDefault();
    void CTTelephonyCenterAddObserver(CFNotificationCenterRef center, const void *observer, CFNotificationCallback callBack, CFStringRef name, const void *object, CFNotificationSuspensionBehavior suspensionBehavior);
    void CTTelephonyCenterRemoveObserver(CFNotificationCenterRef center, const void *observer, CFStringRef name, const void *object);
    void CTTelephonyCenterRemoveEveryObserver(CFNotificationCenterRef center, const void *observer);

    void CTIndicatorsGetSignalStrength(long int *raw, long int *graded, long int *bars);

#pragma mark - Definitions

    /* For use with the CoreTelephony notification system. */
    extern CFStringRef kCTIndicatorsSignalStrengthNotification;

#if __cplusplus
}
#endif

Мой код Swift:

let callback: CFNotificationCallback = { (center: CFNotificationCenter?, observer: UnsafeRawPointer?, name: CFString?, object: UnsafeRawPointer?, info: CFDictionary?) -> Void in
    // ...
}

CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault().takeUnretainedValue(), nil, callback, kCTIndicatorsSignalStrengthNotification.takeUnretainedValue(), nil, .coalesce)

Тем не менее, я не могу получить подпись моего completion переменная, чтобы соответствовать требованиям CFNotificationCallback typealias.

Cannot convert value of type
'(CFNotificationCenter?, UnsafeRawPointer?, CFString?, UnsafeRawPointer?, CFDictionary?) -> Void'
to specified type
'CFNotificationCallback' (aka '@convention(c) (Optional<CFNotificationCenter>, Optional<UnsafeMutableRawPointer>, Optional<CFNotificationName>, Optional<UnsafeRawPointer>, Optional<CFDictionary>) -> ()')

Как я могу получить @convention(c) замыкания, чтобы красиво играть в Swift?

2 ответа

Решение

Позволение компилятору сделать вывод подписи замыкания работает нормально:

let callback: CFNotificationCallback = { center, observer, name, object, info in
    //works fine
}

Пытаюсь уточнить @convention(c) в объявлении замыкания выдает ошибку:

let callback: CFNotificationCallback = { @convention(c) (center: CFNotificationCenter?, observer: UnsafeRawPointer?, name: CFString?, object: UnsafeRawPointer?, info: CFDictionary?) -> Void in
    //Attribute can only be applied to types, not declarations.
}

Похоже, что происходит, когда вы вручную объявляете тип замыкания, это заставляет компилятор использовать именно этот тип. Но технически это объявление закрытия, а не объявление типа, поэтому @convention атрибут не разрешен Когда компилятору разрешается выводить тип замыкания (из типа переменной, в которой он хранится), он также может выводить атрибут.

      class SomeClass {
   func someFunc() {
       CFNotificationCenterAddObserver(nc, nil, queryProgress_cust, kMDQueryProgressNotification, nil, .deliverImmediately)
   }
}

// IMPORTANT: Following code must be NOT related to some class or struct(!!!!)
// "_cust" added for being sure that function will have no duplicates... because of absolutely contrintuitive errors will tell you nothing
fileprivate func queryProgress_cust(_ notifCenter: CFNotificationCenter?, _ observer: UnsafeMutableRawPointer?, _ name: CFNotificationName?, _ obj: UnsafeRawPointer?, _ cfDict: CFDictionary?) {
    //code
}
Другие вопросы по тегам