第一次调用NSURLSession不返回数据

一般来说,有必要为networking实施一个class级。 这是一个类,将采取一个url,并提供数据。 所有这些都是为了不打分额外的逻辑控制器。 我遇到过这样的问题,当你第一次创build一个View时,数据不会来。 这是networking类:

private static var dataTask: NSURLSessionDataTask? private static var dataJSON: NSData? private static var sessionConfig: NSURLSessionConfiguration = { var configuration = NSURLSessionConfiguration.defaultSessionConfiguration() configuration.allowsCellularAccess = false configuration.HTTPMaximumConnectionsPerHost = 2 configuration.HTTPAdditionalHeaders = ["Accept": "application/json"] configuration.timeoutIntervalForRequest = 30.0 configuration.timeoutIntervalForResource = 60.0 return configuration }() static func getListObjectsBy(url: String?) -> NSData? { let session = NSURLSession(configuration: sessionConfig) log.debug("DataTask start") dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in log.debug("if error = error") if let error = error { print(error.localizedDescription) } else if let httpResponse = response as? NSHTTPURLResponse { log.debug("if httpResponse") if httpResponse.statusCode == 200 { dataJSON = data } else { print("Bad request") } } } dataTask?.resume() log.debug("DataTask Resume") return dataJSON } 

方法viewDidLoad在我的主控制器中:

 let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") print(String(response)) 

我的日志说,我的数据返回零。 注意,我在两个控制器之间切换SWRevealViewController。 当重新加载主视图控制器时,数据被返回。 我做什么?

在这里input图像描述

你似乎误解了这是一个asynchronous调用。

 static func getListObjectsBy(url: String?) -> NSData? { let session = NSURLSession(configuration: sessionConfig) log.debug("DataTask start") dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in // Everything in this block is happening on a separate thread. log.debug("if error = error") if let error = error { print(error.localizedDescription) } else if let httpResponse = response as? NSHTTPURLResponse { log.debug("if httpResponse") if httpResponse.statusCode == 200 { // this won't happen until the data comes back from the remote call. dataJSON = data } else { print("Bad request") } } } // This code here does not wait for the response from the remote. // The call to the remote is sent then this code // is immediately executed WITHOUT WAITING dataTask?.resume() log.debug("DataTask Resume") // dataJSON will be nil until the remote answers. return dataJSON } 

当你这样做:

 let response = Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") print(String(response)) 

遥控器还没有回答,所以你会得到零。

你的下一个问题可能是“我该怎么做?”。 如果不知道你正在做的一切,答案是不清楚的。

主题

执行的多个线程就像两个程序同时运行一样。 想想两个人同时在两个不同的任务上工作。 为了保持界面的高度响应,iOS使用一个执行线程来更新屏幕。 如果一个进程需要很长时间才能运行,那么我们不希望屏幕一直等到完成。 假设您必须从某个远程系统获取数据,而且远程系统速度较慢,那么您的设备将会冻结,直到响应回来。 为了避免这种情况,像调用远程系统的活动在另一个线程中完成。 该请求被发送到操作系统本身,操作系统被告知在操作完成时回叫。

这是在这里发生的事情。
设置发送到操作系统的请求。

 dataTask = session.dataTaskWithURL(NSURL(string: url!)!) 

告诉操作系统开始工作。

 dataTask?.resume() 

这个块是callbackAKA的closures。 远程调用完成后,iOS将运行此代码。

 dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { // Closure starts here // Gets called when the remote has sent a response. (data, response, error) in // Everything in this block is happening on a separate thread. log.debug("if error = error") etc } 

这意味着在打印输出之前,您必须等到响应回来。 你可以在你的函数中使用闭包来做到这一点。

 public typealias CompletionHandler = (data: NSData?, error: NSError?) -> Void static func getListObjectsBy(url: String?, completion: CompletionHandler) { let session = NSURLSession(configuration: sessionConfig) log.debug("DataTask start") dataTask = session.dataTaskWithURL(NSURL(string: url!)!) { (data, response, error) in // Everything in this block is happening on a separate thread. log.debug("if error = error") if let error = error { print(error.localizedDescription) } else if let httpResponse = response as? NSHTTPURLResponse { log.debug("if httpResponse") if httpResponse.statusCode == 200 { // this won't happen until the data comes back from the remote call. } else { print("Bad request") } } // Call your closure completion(data, error) } // This code here does not wait for the response from the remote. // The call to the remote is sent then this code // is immediately executed WITHOUT WAITING dataTask?.resume() log.debug("DataTask Resume") } 

在你的调用代码中,你可以这样做:

 Network.getListObjectsBy("http://lb.rmc.su/api-dev/v2/wc/5") { (data, error) in if let data == data { print(data) } }