使用Swift的C API
我试图跟踪networking状态。 我经历了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.将主机string转换为UTF8。
我必须将主机string转换为UTF8并将其传递到SCNetworkReachabilityCreateWithName方法。 我无法在Objective-C中find与UTF8String
属性完全相同的Swift。 但是String
types有一个名为utf8
的属性。 根据文件 ,
通过迭代utf8属性,可以访问string的UTF-8表示forms。 该属性的types为String.UTF8View,它是无符号8位(UInt8)值的集合,对于string的UTF-8表示中的每个字节都有一个值:
我怎样才能得到一个string的完整的UTF8表示,而不是一个无符号的8位(UInt8)值的集合?
2. SCNetworkReachabilitySetCallback的callback函数。
这个函数的第二个参数需要SCNetworkReachabilityCallBack
types的SCNetworkReachabilityCallBack
。 我潜入源文件,发现它实际上是一个typealias
。
typealias SCNetworkReachabilityCallBack = CFunctionPointer<((SCNetworkReachability!, SCNetworkReachabilityFlags, UnsafeMutablePointer<Void>) -> Void)>
我是这样定义的
let reachabilityCallBack: SCNetworkReachabilityCallBack = { }()
但是,我得到错误返回在一个封闭期望返回“SCNetworkReachabilityCallBack”时,在该typealias中,你可以清楚地看到,它返回Void
。
这是否是错误的方式?
这些是我面临的问题。 我已经在这个几个小时没有运气,所以我非常感谢任何帮助。
谢谢。
你的第一个问题可以用
let reachability = host.withCString { SCNetworkReachabilityCreateWithName(nil, $0).takeRetainedValue() }
在闭包内部, $0
是一个指向String的NUL终止的UTF-8表示的指针。
更新:正如Nate Cook在一个已经被删除的答案中所说的那样,在这里也可以直接传递一个Swiftstring给一个带有UnsafePointer<UInt8>
的函数:
let reachability = SCNetworkReachabilityCreateWithName(nil, host).takeRetainedValue()
不幸的是,(据我所知)目前还没有解决你的第二个问题。 SCNetworkReachabilitySetCallback
需要一个指向C函数的指针作为第二个参数,目前没有方法可以传递Swift函数或闭包。 请注意, SCNetworkReachabilityCallBack
的文档SCNetworkReachabilityCallBack
显示了Objective-C,但没有显示Swift。
另请参见Swift不能与函数指针一起使用吗? 。
Swift 2的更新:现在可以将Swift闭包传递给一个带有函数指针参数的C函数。 此外, SCNetworkReachabilityCreateWithName()
不会返回非托pipe对象:
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)