我正在重新设计我的coreData方法,以使用async和wait,但在Swift中理解这些队列仍然存在问题,也许你们可以帮我。。
问题是,我想在函数"内处理的每个步骤之后收集反馈(logComment(;newUpdateMethod(("对我来说唯一有效的方法是:@MainActor";在功能前面
据我所知,这意味着我强制该函数在主队列上运行,而不是在后台队列上运行异步作业。。由于该主队列,我能够填充变量";logComment"并将其返回给VC,VC称之为。。但我不确定,如果这种方式真的有必要,就必须有另一种方式来实现。。。我试图将logComment语句放在DispatchQueue.main.sync块中与主队列对话,但仍然:"捕获的var"logComment"在并发执行代码中的突变";
我的核心数据方法
- 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
}
- 更新方法
@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。。所以警卫在做它的工作
我想是我想出来的:(伙计们!