难以理解 Swift 中的队列(异步等待)



我正在重新设计我的coreData方法,以使用async和wait,但在Swift中理解这些队列仍然存在问题,也许你们可以帮我。。

问题是,我想在函数"内处理的每个步骤之后收集反馈(logComment(;newUpdateMethod(("对我来说唯一有效的方法是:@MainActor";在功能前面

据我所知,这意味着我强制该函数在主队列上运行,而不是在后台队列上运行异步作业。。由于该主队列,我能够填充变量";logComment"并将其返回给VC,VC称之为。。但我不确定,如果这种方式真的有必要,就必须有另一种方式来实现。。。我试图将logComment语句放在DispatchQueue.main.sync块中与主队列对话,但仍然:"捕获的var"logComment"在并发执行代码中的突变";

我的核心数据方法

  1. json获取方法
import UIKit
import CoreData
class CoreDataInteraction {
//(...)
func getRemoteData() async throws -> [RemoteData] {
var remoteData = [RemoteData]()

do {
let url = URL(string: "***")!
let urlRequest = URLRequest(url: url)
let (data, _) =  try await URLSession.shared.data(for: urlRequest)
remoteData = try JSONDecoder().decode([RemoteData].self, from: data)
}catch{
let url = Bundle.main.url(forResource: "remoteData", withExtension: "json")    // use local data instead
let urlRequest = URLRequest(url: url!)
let (data, _) =  try await URLSession.shared.data(for: urlRequest)
remoteData = try JSONDecoder().decode([RemoteWire].self, from: data)

DispatchQueue.main.sync { Logging.insertError(message: error.localizedDescription, location: "get json data") }
}
return remoteData
}
  1. 更新方法
@MainActor  // really necessary ?
func newUpdateMethod(completion: @escaping (String?) -> Void){
var logComment:String = ""
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = RemoteData.fetchRequest() as NSFetchRequest<RemoteData>

Task {
do {
// Step 1
let jsonData = try await getRemoteData()
logComment = logComment + "n Line 1"
// Step 2
var existingData = try context.fetch(request);
logComment = logComment + "n Line 2"
// Step 3 comparison..
// ...
logComment = logComment + "n Line 3"
// Step 4 ...
// continue . . .


}
completion(logComment)
}

}
}

这是VC函数,它调用接收反馈的更新方法,并将其放入UI

class SettingsVC: UIViewController {
//(...)
@IBAction func updateButtonPressed(_ sender: Any) {
//MARK: NEW Update processing
self.LoadingStart()
myCoreData.newUpdateMethod() {(success) in
self.LoadingStop()
self.updateTextField.font = UIFont.systemFont(ofSize: 12.0)
self.updateTextField.text = success
self.updateButton.isEnabled = false
}
}
}

除了@MAinActor,我没有找到其他方法来让这件事成功。。必须有一种方法从Task/do后台队列中获取变量的值,否则在我的理解中是毫无用处的很明显,我在理解中遗漏了一些东西:/

我想我已经解决了。。看看:

func newUpdateMethod2() async -> String {
var logComment:String = ""
let context = await (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = RemoteData.fetchRequest() as NSFetchRequest<RemoteData>

let jsonData = try? await getRemoteData()
guard jsonData != nil else {
Logging.insertError(message: "error creating json source", location: "newUpdateMethod2")
logComment = logComment + "⚠️  Error collecting json source"
return logComment
}

var existingData = try? context.fetch(request)
logComment = logComment + "n Line 2(existing data count: (existingData!.count))"

return logComment
}

这是调用部分:

@IBAction func updateButtonPressed(_ sender: Any) {
//MARK: NEW Update processing
Task {
do {
self.LoadingStart()
let feedback = await myCoreData.newUpdateMethod2()
self.LoadingStop()
self.updateTextField.font = UIFont.systemFont(ofSize: 12.0)
self.updateTextField.text = feedback
self.updateButton.isEnabled = false
print("feedback = (feedback)")
}
}

不再有完成处理程序:(

我不得不用guard而不是catch来帮助自己,因为我不想再次将所有代码封装在do{}语句中,并且找不到其他方法在没有do{}的情况下使用catch。。所以警卫在做它的工作

我想是我想出来的:(伙计们!

最新更新