使用 Swift 的 C API [英] Working with C APIs from Swift

查看:42
本文介绍了使用 Swift 的 C API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to keep track of the network status. I went through the code of the FXReachability. Specifically the following method.

- (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,但遇到了一些问题.

What it does is it keeps checking the connection to the specified host. I'm trying to convert this method to Swift and I'm having a couple of problems.

1.将主机字符串转换为 UTF8.

我必须将主机字符串转换为 UTF8 并将其传递到 SCNetworkReachabilityCreateWithName 方法.我在 Objective-C 中找不到 UTF8String 属性的确切 Swift 等价物.但是对于 String 类型有一个名为 utf8 的属性.根据文档

I have to convert the host string to UTF8 and pass it into the SCNetworkReachabilityCreateWithName method. I can't find the exact Swift equivalent of UTF8String property in Objective-C. But there is a property called utf8 for the String type. According to the documentation,

您可以通过迭代字符串的 utf8 属性来访问字符串的 UTF-8 表示.此属性的类型为 String.UTF8View,它是无符号 8 位 (UInt8) 值的集合,字符串的 UTF-8 表示中的每个字节对应一个值:

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) 值的集合?

How can I get a complete UTF8 representation of a string instead of a collection of unsigned 8-bit (UInt8) values?

2.的回调函数SCNetworkReachabilitySetCallback.

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

Th second parameter of this function expects something of type SCNetworkReachabilityCallBack. I dived in to the source file and found out that it's actually a typealias.

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

我是这样定义的.

let reachabilityCallBack: SCNetworkReachabilityCallBack = {

}()

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

But I get the error Missing return in a closure expected to return 'SCNetworkReachabilityCallBack' when in that typealias you can clearly see that it returns Void.

这是错误的做法吗?

这些是我面临的问题.我已经在这工作了几个小时但运气不佳,所以我非常感谢您的帮助.

These are the problems I'm facing. I've been at this for hours now with no luck so I'd really appreciate any help.

谢谢.

推荐答案

你的第一个问题可以用

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

在闭包内部,$0 是一个指向 NUL 终止的 UTF-8 表示的指针字符串.

Inside the closure, $0 is a pointer to the NUL-terminated UTF-8 representation of the String.

更新:正如 Nate Cook 在现已删除的答案以及此处,您实际上可以将 Swift 字符串传递给采用 UnsafePointer<UInt8> 的函数直接:

Update: As Nate Cook said in a now deleted answer and also here, you can actually pass a Swift string to a function taking a UnsafePointer<UInt8> directly:

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

<小时>

不幸的是(据我所知)目前没有解决您的第二个问题的方法.SCNetworkReachabilitySetCallback 需要一个指向 C 函数的指针作为第二个参数,并且目前没有传递 Swift 函数或闭包的方法.请注意 SCNetworkReachabilityCallBack只显示 Objective-C 而没有 Swift.


Unfortunately there is (as far as I know) currently no solution to your second problem. SCNetworkReachabilitySetCallback expects a pointer to a C function as second parameter, and there is currently no method to pass a Swift function or closure. Note that the documentation for SCNetworkReachabilityCallBack shows only Objective-C but no Swift.

另请参阅Swift 是否不能使用函数指针?.

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

Update for Swift 2: It is now possible to pass a Swift closure to a C function taking a function pointer parameter. Also SCNetworkReachabilityCreateWithName() does not return an unmanaged object anymore:

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)

这篇关于使用 Swift 的 C API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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