我正在学习Swift,但是我在ViewDidLoad中有一个Int类型的变量(跟随者),我将该值设置为默认值0。然后,我执行一个Json Request并返回1数组,并将Followers的值设置为Json Array内部的任何数字788。但是,当我随后执行“打印”时,该值始终保持为0。这是我的代码,它会更有意义
override func viewDidLoad() { super.viewDidLoad() var followers = 0 // Sent HTTP Request sessionn.dataTask(with:requestt, completionHandler: {(data, response, error) in if error != nil { // print(error) } else { do { let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any] if let Profiles = parsedData["data"] as! [AnyObject]? { for Profiles in Profiles { if let follow = Profiles["followers"] as? Int { self.followers = follow // The value here says 788 print(self.followers) } } DispatchQueue.main.async { } } } catch let error as NSError { print(error) } } }).resume() print("Followers is") // The value here says 0 every time print(followers) // I have even tried print(self.followers) }
如您所见,followers变量设置为0,当我执行HttpPost时,可以看到当我有 print(self.followers) 时,变量设置为788, 但是当我访问该变量时,在Loop之外,它的值返回到0。在通过构建应用程序学习Swift时,如何纠正该错误。
您误解了异步代码的工作原理。
设置NSSession数据任务时,在发出task.resume()网络请求之前,将立即返回调用。
NSSession
task.resume()
您应该将用于处理响应的代码放在完成处理程序中。即使您The value here says 0在网络任务上调用恢复后发生打印语句,但尚未检索到数据。
The value here says 0
想象一下,您正在做晚餐,然后您送孩子出去拿一袋面粉。你说:“孩子,给我拿点面粉。回来的时候,按下公寓门上的蜂鸣器,我会嗡嗡作响。”
然后,您又回到晚餐的其他部分做饭,但是您不希望告诉孩子去吃面粉的那一刻,您就会低头看着柜台,面粉就在那里了。您知道必须等到蜂鸣器发出嗡嗡声,然后您的孩子才能得到面粉。
提交网络任务就是这样。拨打电话task.resume()类似于您对面粉的要求。您提交了请求,但是在请求完成处理之前继续进行操作。在 完成处理程序 运行的是让你知道你的孩子又回来了面粉中的蜂鸣器。
我已经在Github上创建了一个项目,演示了如何在URLSession中使用完成处理程序。该项目称为 Async_demo (链接)
关键部分是downloadFileAtURL()DownloadManager.swift中的方法
downloadFileAtURL()
注意函数如何将完成处理程序作为参数。该函数使用完成处理程序创建URLSession数据任务。在完成处理程序内部,对于URLSession数据任务,该downloadFileAtURL()函数调用传递给它的完成处理程序。它用于DispatchQueue.main.async()在主线程上调用完成处理程序。
URLSession
DispatchQueue.main.async()
该演示项目使用URLSession数据任务,并显式禁用数据缓存,以便每次单击下载按钮时都将重新加载映像。
这是downloadFileAtURL()DownloadManager.swift中该函数的代码:
func downloadFileAtURL(_ url: URL, completion: @escaping DataClosure) { //We create a URLRequest that does not allow caching so you can see the download take place let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0) let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in //Perform the completion handler on the main thread DispatchQueue.main.async { //Call the copmletion handler that was passed to us completion(data, error) } } dataTask.resume() //When we get here the data task will NOT have completed yet! }
视图控制器具有名为的IBAction函数handledDownloadButton()。该功能:
handledDownloadButton()