请求超时 NSURLSession

3

你好,我使用以下代码向服务器发送请求。如何在此函数中添加超时时间?

static func postToServer(url:String,var params:Dictionary<String,NSObject>, completionHandler: (NSDictionary?, String?) -> Void ) -> NSURLSessionTask {


        let request = NSMutableURLRequest(URL: NSURL(string: url)!)


        let session = NSURLSession.sharedSession()

        request.HTTPMethod = "POST"

    if(params["data"] != "get"){
        do {

            let data = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)

            let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)!
            print("dataString is  \(dataString)")

            request.HTTPBody = data


        } catch {
            //handle error. Probably return or mark function as throws
            print("error is \(error)")
            //return
        }

    }
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = session.dataTaskWithRequest(request) {data, response, error -> Void in
            // handle error

            guard error == nil else { return }
            request.timeoutInterval = 10


           print("Response: \(response)")
            let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
             completionHandler(nil,"Body: \(strData!)")
          //print("Body: \(strData!)")

            let json: NSDictionary?
            do {
                json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
            } catch let dataError {
                // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
                print(dataError)
                let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
              print("Error could not parse JSON: '\(jsonStr)'")
                completionHandler(nil,"Body: \(jsonStr!)")

                // return or throw?
                return
            }


            // The JSONObjectWithData constructor didn't return an error. But, we should still
            // check and make sure that json has a value using optional binding.
            if let parseJSON = json {
                // Okay, the parsedJSON is here, let's get the value for 'success' out of it

                completionHandler(parseJSON,nil)
                //let success = parseJSON["success"] as? Int
                //print("Succes: \(success)")
            }
            else {
                // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("Errors could not parse JSON: \(jsonStr)")
                completionHandler(nil,"Body: \(jsonStr!)")
            }

        }

        task.resume()
        return task
    }

我也进行了一些搜索,发现可以使用这个函数

let request = NSURLRequest(URL: url!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)

而不是这样

let request = NSMutableURLRequest(URL: NSURL(string: url)!)

但问题是,如果我使用上述函数,则无法设置这些变量。
request.HTTPBody = data
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

请有经验的人给我建议,如何在我的函数中添加超时功能。

4个回答

4
NSMutableRequest有一个属性timeoutInterval,您可以设置它。 这里是苹果的文档,展示了如何设置超时时间。
他们已经说明:
如果在连接尝试期间请求保持空闲状态的时间超过超时时间,则认为请求已超时。默认的超时时间是60
请注意,超时不会保证网络调用将在超时后终止,如果网络调用没有在超时时间内完成。例如:假设您将超时时间设置为60秒。连接可能仍然处于活动状态,并且在60秒后不会终止。只有在完整的60秒时间段内没有数据传输时才会发生超时。
例如:考虑以下情况这不会导致超时
  • t=0到t=59秒=>没有数据传输(总共59秒)
  • t=60到t=62 => 一些数据在t=60s到达(总共2秒)
  • t=63到t=100 =>没有数据传输(总共37秒)
  • t=100到t=260 =>剩余数据传输并完成网络请求(总共160秒)
  • 考虑以下情况:现在考虑以下情况超时发生在t=120
  • t=0到t=59秒=>一些数据在t=59之前传输(总共59秒)
  • t=60到t=120 =>没有数据传输(总共60秒)

  • 4

    您无法修改请求,因为某种原因您使用了不可变选项。由于NSMutableURLRequest是NSURLRequest的子类,您可以使用完全相同的初始化器init(URL:cachePolicy:timeoutInterval:)创建一个可变实例并设置默认超时时间。然后根据需要配置(变异)此请求。

    let request = NSMutableURLRequest(URL: url!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)
    

    好的,谢谢。它正在工作。我想问的最后一个问题是如何将nil返回给我的调用函数。我正在做这个if(response == nil){ completionHandler(nil,"nil")但它不起作用。 - hellosheikh

    2

    使用NSURLSessionConfiguration指定超时时间:

    let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
    sessionConfig.timeoutIntervalForRequest = 30.0 //请求超时时间为30秒
    sessionConfig.timeoutIntervalForResource = 30.0 //响应超时时间为30秒
    
    let session  = NSURLSession(configuration: sessionConfig)
    

    0

    NSMutableURLRequest也有这个方法:

    let request = NSMutableURLRequest(URL:  NSURL(string: url)!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5)
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接