【问题标题】:URLSession dataTask does not runURLSession dataTask 不运行
【发布时间】:2018-10-17 15:49:56
【问题描述】:

我对这段代码有疑问。我正在“非常糟糕的网络”配置文件下使用 Network Link Conditioner 测试我的应用程序,并且在用户的互联网连接不佳的情况下,这个 dataTask 永远不会运行。如果连接良好,则此代码可以正常工作。我猜它没有运行是因为连接不好,但是我该如何处理这种情况,因为我无法从完成处理程序中获得响应,因为该行永远不会运行?

let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
                    do {
                        print("RUNNING RECEIPT UPLOAD TASK")
                        if let jsonObj: [String : AnyObject] = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? [String : AnyObject] {
                            if let resultData: [String : AnyObject] = jsonObj["result"] as? [String : AnyObject] {
                                if let status: Bool = resultData["status"] as? Bool {
                                    if status {
                                        completion(status, nil, resultData)
                                    } else {
                                        if let errorMessage: String = resultData["message"] as? String {
                                            completion(status, errorMessage, resultData)
                                        } else {
                                            completion(status, "FAILED RECEIPT UPLOAD", resultData)
                                        }
                                    }
                                }
                            } else {
                                completion(false, "FAILED RECEIPT UPLOAD", nil)
                            }
                        } else {
                            completion(false, "FAILED RECEIPT UPLOAD", nil)
                        }
                    } catch _ {
                        completion(false, "FAILED RECEIPT UPLOAD", nil)
                    } 

                })

                task.resume()

如果我在使用 Reachability 或以下代码块运行它之前尝试测试活动的 Internet 连接,即使有连接但它很差,它也会返回 true,所以我无法通过测试来处理未运行的 dataTask首先连接。

static func isInternetAvailable() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }

        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
            return false
        }
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        return (isReachable && !needsConnection)

    }

【问题讨论】:

  • 您可以为请求设置请求超时...并在超时后向用户显示消息,例如互联网连接不佳或其他什么。

标签: swift


【解决方案1】:

我猜它没有运行是因为连接不好,但是我该如何处理这种情况,因为我无法从完成处理程序中获得响应,因为该行永远不会运行?

您应该简单地接受您可能无法从完成处理程序中得到响应。这就是异步操作的全部意义:您可能很快就会收到响应,可能需要很长时间,也可能永远不会。您的代码应该以能够处理该问题的方式编写。

默认情况下,当你创建一个 URLSession 时,它的配置 waitsForConnectivitytrue。您应该使用 Reachability 来了解是否存在连接;你应该开始任务并退后一步。任务会在可能的情况下发生。

但是,如果这是不可接受的并且您需要尽早失败,则将配置的 waitsForConnectivity 设置为 false。然后您将因超时而失败,可能在一分钟内(默认值)。

然而,还应该指出的是,通过使用带有完成处理程序的数据任务,您有点自取其辱。这是一种非常有限的方法。给会话一个委托并实现委托方法会更好,以便在发生时接收有关正在发生的事情的完整信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 2018-07-14
    • 2019-04-18
    相关资源
    最近更新 更多