swift - 修复 NSURLConnection 弃用从 Swift 1.2 到 2.0

标签 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 在单独的线程上执行。

我担心的是,我能否像 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/

相关文章:

swift : Enum case not found in type

xcode - 在 iPad (iOS 8) 上运行 Xcode 6 应用程序时出现 "Installation of apps is prohibited by a policy on the device."错误

ios - 如何在 xcode 和 swift 中使用不受支持的类(新功能)构建项目

ios - 有效的配置文件均不包含设备 - 分发

swift - 通过符合 Swift 2 中的协议(protocol)扩展类型化数组

ios - 创建预期的 UI 行为,同时也不会收到破坏约束警告

swift - coreML 验证输入失败

ios - 如何在 iOS 9 上以横向和纵向模式显示 iPad Launchscreen Storyboard?

iOS 后台 App Fetch 不工作

ios - 删除在 View 上绘制的线