我有一个用 Swift 1.2 编写的函数,用于检查地址或 IP 的可达性。在这里:
func isHostConnected(hostAddress : String) -> Bool
{
var response : NSURLResponse?
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress)!)
request.timeoutInterval = 3
let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil)
return ((response as? NSHTTPURLResponse)!.statusCode == 200)
}
现在,NSURLConnection
已被弃用,根据 Xcode 的建议,我尝试使用 NSURLSession.dataTaskWithRequest
编写它,这里是:
func isHostConnected(hostAddress : String) -> Bool
{
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
request.timeoutInterval = 3
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
var responseCode = -1
session.dataTaskWithRequest(request, completionHandler: {(data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in
responseCode = (response as? NSHTTPURLResponse)!.statusCode
})!.resume()
return (responseCode == 200)
}
上面的代码总是返回 false(很明显),因为 completionHandler
在单独的线程上执行。
我担心的是,我能否像 sendSynchronousRequest
那样通过阻止它来使 completionHandler()
在 MainThread 上运行。
我有理由不在这里使用“Apple 的可达性”。
任何建议都会有所帮助。 :)
最佳答案
(重复我在 https://stackoverflow.com/a/30670518/1187415 中的论点:)
Checking if a resource exists on a server requires sending a HTTP request and receiving the response. TCP communication can take some amount of time, e.g. if the server is busy, some router between the client and the server does not work correctly, the network is down etc.
That's why asynchronous requests are always preferred. Even if you think that the request should take only milliseconds, it might sometimes be seconds due to some network problems. And – as we all know – blocking the main thread for some seconds is a big no-no.
也就是说,您可以使用“计数信号量”或“调度组”来等待某个异步任务的完成。 您应该不在主线程上使用它。阻塞主线程 最多 3 秒是 Not Acceptable !
func isHostConnected(hostAddress : String) -> Bool
{
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
request.timeoutInterval = 3
request.HTTPMethod = "HEAD"
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var responseCode = -1
let group = dispatch_group_create()
dispatch_group_enter(group)
session.dataTaskWithRequest(request, completionHandler: {(_, response, _) in
if let httpResponse = response as? NSHTTPURLResponse {
responseCode = httpResponse.statusCode
}
dispatch_group_leave(group)
})!.resume()
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
return (responseCode == 200)
}
备注:
- 将 HTTP 方法设置为“HEAD”是一个小的优化,因为 服务器只发送没有实际数据的响应头。
- 在非法主机名的情况下,
response
将是nil
,并且responseCode = (response as?NSHTTPURLResponse)!.statusCode
会崩溃。
关于swift - 修复 NSURLConnection 弃用从 Swift 1.2 到 2.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30951771/