修复从Swift 1.2到2.0的NSURLConnection弃用

its*_*dra 1 swift ios9 xcode7 swift2

我有一个用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)
}
Run Code Online (Sandbox Code Playgroud)

现在,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)
}
Run Code Online (Sandbox Code Playgroud)

上面的代码总是返回false(它的明显),因为completionHandler在单独的Thread上执行.

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

我有理由不在这里使用'Apple's Reachabilty'.

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

Mar*_*n R 11

(重复我的论点来自/sf/answers/2146936291/ :)

检查服务器上是否存在资源需要发送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)
}
Run Code Online (Sandbox Code Playgroud)

备注:

  • 将HTTP方法设置为"HEAD"是一个小优化,因为服务器仅发送没有实际数据的响应头.
  • 在一个非法的主机名的情况下,responsenilresponseCode = (response as? NSHTTPURLResponse)!.statusCode会崩溃.