在 Swift 中使用 CFNotificationCallback,或者在 Swift 中使用 @convention(c) 块 [英] Using CFNotificationCallback in Swift, or, @convention(c) blocks in Swift

查看:22
本文介绍了在 Swift 中使用 CFNotificationCallback,或者在 Swift 中使用 @convention(c) 块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用(现在是私有的)CTTelephonyCenterAddObserver C 函数和 CFNotificationCallback 回调块来收听 CoreTelephony 通知.

我的桥接头(用于外部私有 C 函数):

#include #if __cplusplus外部C"{#万一#pragma mark - API/* 这个 API 是对 CFNotificationCenter 的模仿.*/CFNotificationCenterRef CTTelephonyCenterGetDefault();void CTTelephonyCenterAddObserver(CFNotificationCenterRef center, const void *observer, CFNotificationCallback callBack, CFStringRef name, const void *object, CFNotificationSuspensionBehavior pauseBehavior);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 - 定义/* 用于 CoreTelephony 通知系统.*/extern CFStringRef kCTIndicatorsSignalStrengthNotification;#if __cplusplus}#万一

我的 Swift 代码:

let callback: CFNotificationCallback = { (center: CFNotificationCenter?, Observer: UnsafeRawPointer?, name: CFString?, object: UnsafeRawPointer?, info: CFDictionary?) ->作废//...}CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault().takeUnretainedValue(), nil, callback, kCTIndicatorsSignalStrengthNotification.takeUnretainedValue(), nil, .coalesce)

但是,我无法获得 completion 变量的签名来匹配 CFNotificationCallback 类型别名的要求.

<块引用>

无法转换类型的值'(CFNotificationCenter?,UnsafeRawPointer?,CFString?,UnsafeRawPointer?,CFDictionary?)->空白'到指定类型'CFNotificationCallback'(又名'@convention(c) (Optional<CFNotificationCenter>, Optional<UnsafeMutableRawPointer>, Optional<CFNotificationName>, Optional<UnsafeRawPointer>, Optional<CFDictionary>)'-)

我怎样才能让 @convention(c) 闭包在 Swift 中很好地发挥作用?

解决方案

让编译器推断闭包的签名工作正常:

let callback: CFNotificationCallback = { center,observer, name, object, info in//工作正常}

尝试在闭包的声明中指定 @convention(c) 会出现错误:

let callback: CFNotificationCallback = { @convention(c) (center: CFNotificationCenter?, Observer: UnsafeRawPointer?, name: CFString?, object: UnsafeRawPointer?, info: CFDictionary?) ->作废//属性只能应用于类型,不能应用于声明.}

似乎发生的事情是,当您手动声明闭包的类型时,它会强制编译器使用该确切类型.但这在技术上是一个闭包声明而不是类型声明,所以 @convention 属性是不允许的.当编译器被允许推断闭包的类型(从它被存储的变量的类型)时,它也可以推断属性.

I am trying to listen to CoreTelephony notifications using the (now private) CTTelephonyCenterAddObserver C function and CFNotificationCallback callback blocks.

My bridging header (to extern the private C functions):

#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

My Swift code:

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

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

However, I can't get the signature of my completion variable to match the requirements of the 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>) -> ()')

How can I get @convention(c) closures to play nicely in Swift?

解决方案

Letting the compiler infer the closure's signature works fine:

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

Trying to specify @convention(c) in the closure's declaration gives an error:

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.
}

It seems like what's going on is that when you manually declare the closure's type, it forces the compiler to use that exact type. But that's technically a closure declaration and not a type declaration, so the @convention attribute isn't allowed. When the compiler is allowed to infer the closure's type (from the type of the variable it is being stored in), it can infer the attribute too.

这篇关于在 Swift 中使用 CFNotificationCallback,或者在 Swift 中使用 @convention(c) 块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆