执行网络调用并继续 - 异步任务
perform network call and proceed - asynchronous task
一年前才开始学习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 函数中执行了这些步骤后,我该如何继续?
如果我尝试将这些结果写入完成块内的任何 UI 元素、textField 或其他任何元素,我会收到一条错误消息,指出这必须在主线程中发生,如果我在完成块外执行这些行太早执行,还没有结果。
我觉得我对此有理解上的问题,希望你们能帮助我并指导我正确的方向。
由于 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
}
}
}
一年前才开始学习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 函数中执行了这些步骤后,我该如何继续? 如果我尝试将这些结果写入完成块内的任何 UI 元素、textField 或其他任何元素,我会收到一条错误消息,指出这必须在主线程中发生,如果我在完成块外执行这些行太早执行,还没有结果。
我觉得我对此有理解上的问题,希望你们能帮助我并指导我正确的方向。
由于 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
}
}
}