c - 在 Swift 中使用 CFNotificationCallback,或者在 Swift 中使用 @convention(c) block

标签 c swift swift3 core-telephony cfnotification

我正在尝试使用(现已私有(private))CTTelephonyCenterAddObserver C 函数和 CFNotificationCallback 回调 block 来监听 Co​​reTelephony 通知。

我的桥接 header (用于外部私有(private) 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 类型别名的要求。

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 中正常运行?

最佳答案

让编译器推断闭包的签名效果很好:

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 属性。当允许编译器推断闭包的类型(根据存储它的变量的类型)时,它也可以推断属性。

关于c - 在 Swift 中使用 CFNotificationCallback,或者在 Swift 中使用 @convention(c) block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40141675/

相关文章:

C: 二维字符数组问题

ios - 删除按钮 ios swift 的所有动画

ios - 操作按钮未出现在通知 iOS 10 中

swift - UITextField Swift 中只允许使用字母和空格

c - 目标在 Makefile 中的作用是什么?

c - 在 Lua 中从 C 注册函数时如何将模块嵌套到命名空间中?

C 代码永远运行*

ios - 如何检测新的iBeacon?

ios - Toast 的 showMessage 函数未出现在 XLPagerTabStrip 中

swift3 - 如何以编程方式在 iOS 11 中打开蓝牙设置