Ios 使用Swift的C API

Ios 使用Swift的C API,ios,c,swift,utf-8,callback,Ios,C,Swift,Utf 8,Callback,我正在努力跟踪网络状态。我检查了密码。具体来说,可以使用以下方法 - (void)setHost:(NSString *)host { if (host != _host) { if (_reachability) { SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);

我正在努力跟踪网络状态。我检查了密码。具体来说,可以使用以下方法

- (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并将其传递到方法中。我在Objective-C中找不到与
UTF8String
属性完全相同的Swift属性。但是对于
String
类型,有一个名为
utf8
的属性。据报道,

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

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


2。的回调函数。

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

typealias SCNetworkReachabilityCallBack = CFunctionPointer<((SCNetworkReachability!, SCNetworkReachabilityFlags, UnsafeMutablePointer<Void>) -> Void)>
但是我在一个闭包中得到了一个错误,该闭包预期返回“SCNetworkReachabilityCallBack”,在该类型别名中,您可以清楚地看到它返回
Void

这样做是错误的吗


这些就是我面临的问题。我已经干了好几个小时了,运气不好,所以我真的很感谢你的帮助


谢谢。

您的第一个问题可以用

let reachability = host.withCString {
    SCNetworkReachabilityCreateWithName(nil, $0).takeRetainedValue()
}
在闭包内部,
$0
是指向该闭包的以NUL结尾的UTF-8表示形式的指针 绳子

更新:如中所述 现在删除了答案,而且, 实际上,您可以将Swift字符串传递给使用
UnsafePointer
直接:

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

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

另见


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的更新(代码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)

谢谢你,马丁。限制:(一件小事。现在可访问性的类型是
非托管!
。我在将其传递给其他函数时发现错误“非托管”与“SCNetworkReachability”不同。是否有办法解决此问题?@Isuru:我忘了takeRetainedValue()。现在应该可以了。在Swift 3代码中,什么返回或输出告诉您应用程序无法与指定主机联系?@ConfusionTowers:这不是可达性API的内容。比较:“当应用程序发送到网络堆栈中的数据包可以离开本地设备时,远程主机被认为是可访问的。可访问性并不保证主机将实际接收到数据包。”–只有创建TCP连接,您才能看到主机/端口是否存在并可以联系。@MartinR Sweet!谢谢。
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)