gpt4 book ai didi

SwiftUI - 确保从主线程发布值(通过像 receive(on :)) on model updates

转载 作者:行者123 更新时间:2023-12-04 14:15:04 26 4
gpt4 key购买 nike

我的应用程序包含一个资源繁重的操作,该操作根据从 XML 提要中提取的数据填充数组。我不希望此操作锁定主线程(以及为数组提供新数据时的 UI),因此它在后台完成。

    let dispatchQueue = DispatchQueue(label: "concurrent.queue", qos: .utility, attributes: .concurrent)
class XMLHandler: ObservableObject {
let context: NSManagedObjectContext
@Published var myArray: [CustomObject] = []
init(context: NSManagedObjectContext) {
self.context = context
}
...some code...
func populateArray {
dispatchQueue.async {
...xml parsing happens...
(xmlOutputObject) in
for x in xmlOutputObject {
self.myArray.append(x) }
}

在其他地方,我的 SwiftUI View 使用 myArray 来填充它的列表:
struct MyView: View {

@EnvironmentObject var handler: XMLHandler
var body: some View {
List{
ForEach(handler.myArray) { CustomObject in
... generate rows ...
}
}
}

当我的应用程序尝试更新 @Published var myArray: [CustomObject] = [] 时,会发生运行时错误。

不允许从后台线程发布更改;确保在模型更新时从主线程发布值(通过像 receive(on:) 这样的操作符)。

我知道这与采用Combine有关,但老实说我不知道​​从哪里开始。任何帮助,将不胜感激。

我只是希望发生以下情况:
  • 用户按下按钮启动 XML 数据拉取填充 myArray
  • myArray 填充在后台线程上,保持 UI 响应
  • 任务完成后,MyView 中的列表会自动更新。目前,我必须离开 View 并再次返回以刷新列表。
  • 最佳答案

    由于追加发生在循环中,因此您需要决定是要为每个项目发出一次新值,还是为整个更新发出一次新值。如果您不确定,请为整个更新更新一次。

    然后在主队列上执行该操作:

      ...xml parsing happens...
    (xmlOutputObject) in
    DispatchQueue.main.async { // <====
    self.append(contentsOf: xmlOutputObject)
    }

    关键是你不能在多个队列上读取或写入属性。在这种情况下,您要使用的队列是主要队列(因为它驱动 UI)。因此,您必须确保所有属性访问都发生在该队列上。

    关于SwiftUI - 确保从主线程发布值(通过像 receive(on :)) on model updates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61108947/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com