执行网络调用并继续 - 异步任务
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
【讨论】:
以上是关于执行网络调用并继续 - 异步任务的主要内容,如果未能解决你的问题,请参考以下文章