修复从Swift 1.2到2.0的NSURLConnection弃用

时间:2015-06-20 08:10:28

标签: swift xcode7 swift2 ios9

我有一个用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会在单独的线程上执行。

我担心的是,我是否可以通过阻止它来completionHandler()sendSynchronousRequest的方式在MainThread上运行。

我有理由不使用Apple的Reachabilty'这里。

任何建议都会有所帮助。 :)

1 个答案:

答案 0 :(得分:11)

(从https://stackoverflow.com/a/30670518/1187415重复我的论点:)

  

检查服务器上是否存在资源需要发送HTTP   请求并收到回复。 TCP通信可能需要一些   时间量,例如如果服务器忙,一些路由器之间   客户端和服务器无法正常工作,网络已关闭   等

     

这就是为什么异步请求总是首选的原因。即使你   认为请求应该只需要几毫秒,它可能   由于某些网络问题,有时会是秒。而且 - 像我们一样   知道 - 阻塞主线程几秒钟是一个很大的禁忌。

话虽这么说,你可以使用"计数信号量"或者一个"派遣小组"等待一些异步任务的完成。 你应该在主线程上使用它。阻止主线程 最长3秒是不可接受的!

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会崩溃。