执行网络调用并继续 - 异步任务

Posted

技术标签:

【中文标题】执行网络调用并继续 - 异步任务【英文标题】:perform network call and proceed - asynchronous task 【发布时间】:2020-11-22 21:04:20 【问题描述】:

我一年前才开始学习 Swift,所以请耐心等待 :)

我正在通过网络调用下载 JSON 数据,一旦成功接收到这些行,我就会继续清除我的 coreData 实体中的行,并将这些新行重写为 coredata..

我很难理解这个异步过程..

我学到的是我必须使用完成处理程序,但我仍然不能按我需要的方式使用它。特别是当我需要在执行完这 3 个步骤后继续时..

按钮操作的第一次调用:

@IBAction func updateButtonPressed(_ sender: Any) 

    self.myCoreData.update() (success) in // calls my update method
        print(success!) 
        textField.text = success! // not possible bc not in the Mainthread

textField.text = "blabla" // gets executed before the result is available

方法:

func update(completion: @escaping (String?) -> Void)  //parent method which calls sub methods
    var returnValue = ""
    Step1getJson _ in.      // step 1
        self.Step2Delete    // step 2
            self.Step3Save  // step 3
                returnValue = "return Value: \(self.step1Result)"
                completion(returnValue)
            
        
    


func Step1getJson(completion: @escaping (Bool) -> ()) 
    var success = false
    if let url = URL(string: "https:foo") 
        URLSession.shared.dataTask(with: url)  data, response, error in
            guard let data = data else  return 
                do 
                    let parsedJSON = try JSONDecoder().decode([RemoteWire].self, from: data)
                    print("-- Successfully received \(parsedJSON.count) datarows ")
                    self.JSON = parsedJSON
                    self.step1Result = "-- Successfully received \(parsedJSON.count) datarows "
                    success = true

                 catch 
                    print(error)
                
            completion(success)
        .resume()
    


func Step2Delete(completion: () -> Void) 
...delete entity rows
completion()


func Step3Save(completion: () -> Void) 
.. save new JSON rows to coreData
completion()

到目前为止一切正常,当网络下载完成后,第 2 步和第 3 步被成功调用..

但是在我的 updateButtonPressed 函数中执行了这些步骤后,我该如何继续? 如果我尝试将这些结果写入完成块、textField 或其他任何内容中的任何 UI 元素,我会收到一个错误,这必须在主线程中发生,如果我在完成块之外执行它,这些行也会被执行太远早点,当时还没有结果。

我觉得我对此有理解问题,我希望你们能帮助我并引导我朝着正确的方向前进。

【问题讨论】:

其实第 2 步和第 3 步并不是异步的,因为删除行和保存 Core Data 记录默认是同步的。 是的,没错,我尝试了很多东西,我认为这只是第一步,但正如我所说,我只是不明白如何在按钮操作中进行。无论我在完成块之外做什么,它们都会在第 1 步完成之前执行 在闭包内调用textField.text = success并将其分派到主线程。 行得通 - 谢谢你 vadian DispatchQueue.main.async [unowned self] in updateTextField.text = success! 【参考方案1】:

由于 swift 只允许从主线程对 UI 元素进行任何更改或更新,因此您需要调用主线程来更新 UI。 替换下面的代码

@IBAction func updateButtonPressed(_ sender: Any) 

     self.myCoreData.update() (success) in // calls my update method
        print(success!) 
        textField.text = success! // not possible bc not in the Mainthread
     

使用新代码

@IBAction func updateButtonPressed(_ sender: Any) 

    self.myCoreData.update() (success) in // calls my update method
        print(success!)
        DispatchQueue.main.async 
            textField.text = success! // Now possible because it is in main thread
        
    
    

【讨论】:

以上是关于执行网络调用并继续 - 异步任务的主要内容,如果未能解决你的问题,请参考以下文章

Java8——异步编程

十异步

JS异步

SpringBoot--任务:异步任务

使用异步任务

高性能异步爬虫概述