ios - 在 Swift 中使用 C API

标签 ios c swift utf-8 callback

我正在尝试跟踪网络状态。我浏览了 FXReachability 的代码.具体有以下方法。

- (void)setHost:(NSString *)host
{
    if (host != _host)
    {
        if (_reachability)
        {
            SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
            CFRelease(_reachability);
        }
        _host = [host copy];
        _status = FXReachabilityStatusUnknown;
        _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [_host UTF8String]);
        SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
        SCNetworkReachabilitySetCallback(_reachability, ONEReachabilityCallback, &context);
        SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    }
}

它的作用是不断检查与指定主机的连接。我正在尝试将此方法转换为 Swift,但遇到了一些问题。

<强>1。将主机字符串转换为 UTF8。

我必须将主机字符串转换为 UTF8 并将其传递到 SCNetworkReachabilityCreateWithName方法。我在 Objective-C 中找不到与 UTF8String 属性完全相同的 Swift。但是 String 类型有一个名为 utf8 的属性。根据documentation ,

You can access a UTF-8 representation of a String by iterating over its utf8 property. This property is of type String.UTF8View, which is a collection of unsigned 8-bit (UInt8) values, one for each byte in the string’s UTF-8 representation:

如何获得字符串的完整 UTF8 表示而不是无符号 8 位 (UInt8) 值的集合?


<强>2。 SCNetworkReachabilitySetCallback 的回调函数.

此函数的第二个参数需要 SCNetworkReachabilityCallBack 类型的内容。我深入研究了源文件,发现它实际上是一个 typealias

typealias SCNetworkReachabilityCallBack = CFunctionPointer<((SCNetworkReachability!, SCNetworkReachabilityFlags, UnsafeMutablePointer<Void>) -> Void)>

我是这样定义的

let reachabilityCallBack: SCNetworkReachabilityCallBack = {

}()

但我收到错误Missing return in a closure expected to return 'SCNetworkReachabilityCallBack',当在该类型别名中时您可以清楚地看到它返回 Void

这是错误的做法吗?


这些是我面临的问题。我已经在这几个小时了,但没有运气,所以我真的很感激任何帮助。

谢谢。

最佳答案

你的第一个问题可以用

解决
let reachability = host.withCString {
    SCNetworkReachabilityCreateWithName(nil, $0).takeRetainedValue()
}

在封闭内部,$0是指向以 NUL 结尾的 UTF-8 表示的指针 字符串。

更新:作为Nate Cook说在 现在已删除的答案,还有 here , 您实际上可以将 Swift 字符串传递给采用 UnsafePointer<UInt8> 的函数 直接:

let reachability = SCNetworkReachabilityCreateWithName(nil, host).takeRetainedValue()

不幸的是(据我所知)目前没有解决您的第二个问题的方法。 SCNetworkReachabilitySetCallback期望一个指向 C 函数的指针作为第二个 参数,目前还没有传递 Swift 函数或闭包的方法。 请注意 SCNetworkReachabilityCallBack 的文档 仅显示 Objective-C 但不显示 Swift。

另见 Does Swift not work with function pointers? .


Swift 2 更新:现在可以传递 Swift 闭包 到采用函数指针参数的 C 函数。还 SCNetworkReachabilityCreateWithName() 不再返回非托管对象:

let host = "google.com"
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
let reachability = SCNetworkReachabilityCreateWithName(nil, host)!

SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
    print(flags)
}, &context) 

SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)

Swift 3 (Xcode 8) 更新:

let host = "google.com"
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
let reachability = SCNetworkReachabilityCreateWithName(nil, host)!

SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
    print(flags)
    }, &context)

SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(),
                                         CFRunLoopMode.commonModes.rawValue)

关于ios - 在 Swift 中使用 C API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33972084/

相关文章:

c++ - 如何以编程方式将控制台字体设置为光栅字体?

c - 在 C 中打印长度为 char 的缓冲区

ios - 如何在任何尺寸设备上将 ScrollView 的内容大小设置为框架的最大宽度

ios - 更改时 UIView 比例动画过冲

c# - 带有图像的 MonoTouch UITableView

c - 如何使用 fscanf 读取 c(Segmentation Fault) 中的文件?

javascript - 带有 iOS Swift 请求超时的 Express.js 服务器

ios - UIButton 即使在整个区域也没有接触

ios - 如何获取 UIView 当前位置?

ios - UIButton 从四面八方填充图像