SwiftUI 视图不会更新具有子类的已发布对象

SwiftUI view does not update for Published objects with subclasses

因为我的实际代码有点复杂,这里有一个简化的 class 结构,我可以用它重现同样的意外行为。

这是我子class:

的基础数据对象
class People: Identifiable {
    var name: String
    
    required init(name: String) {
        self.name = name
    }
}

class Men: People {
    
}

然后我使用另一个 class,它也充当 superclass,但也使用通用类型 People

class SuperMankind<PlayerType: People> {
    var people: [PlayerType] = []
}

class Mankind: SuperMankind<Men> {

}

现在我想在我的 ViewModel 中使用这个 Mankind subclass,它是一个 ObservableObject。

class ViewModel: ObservableObject {
    @Published var mankind: Mankind
    
    init(_ m: Mankind) {
        mankind = m
    }
}

struct TestView: View {
    @StateObject var viewModel = ViewModel(Mankind())
    var body: some View {
        VStack {
            Button("Add") {
                viewModel.mankind.people.append(Men(name: Int.random(in: 0...1000).description))
            }
            List {
                ForEach(viewModel.mankind.people) {
                    Text([=12=].name)
                }
            }
        }
    }
}

但我不知道为什么单击添加按钮后我的视图不会更新。我发现如果我将以下代码添加到我的按钮操作中,视图就会更新。但是我认为不需要手动调用,所以我认为我做错了什么。

viewModel.objectWillChange.send()

ObservableObject .

我稍微修改了你的代码,它起作用了:

protocol SuperMankind {
    associatedtype PlayerType
    var people: [PlayerType] { get set }
}

struct Mankind: SuperMankind {
    var people: [Men] = []
}

Screenshot here

关于您的解决方案(因为我无法发表评论):

Array<Men> 是一个结构,尽管数组包含 class 引用。这就是为什么您的代码现在可以工作的原因,就像之前您直接在 ObservableObject 中持有对 class 的引用(因此没有更新视图)。

@SwiftSharp 感谢您的回答,associatedType 我没有想到这一点。但是 @Published 字段需要是结构是不正确的考虑这个解决方案,我现在会选择它,因为我不想让我的所有功能都发生变化。

class People: Identifiable {
    var name: String
    
    required init(name: String) {
        self.name = name
    }
}

class Men: People {
    
}

class SuperMankind<PlayerType: People>: ObservableObject {
    @Published var people: [PlayerType] = []
}

class Mankind: SuperMankind<Men> {
}

struct TestView: View {
    @StateObject var viewModel = Mankind()
    var body: some View {
        VStack {
            Button("Add") {
                viewModel.people.append(Men(name: Int.random(in: 0...1000).description))
            }
            List {
                ForEach(viewModel.people) {
                    Text([=10=].name)
                }
            }
        }
    }
}

我的问题是 ViewModel class 不是必需的,而且我的 superclass 包含 people 数组不是 ObervableObject。

编辑 仅在此处完成: 这也将解决我最初的代码问题,使用 ViewModel class,但不是 subclassing ObservableObject 我会从 Mankind subclass,它已经符合通过 subclassing SuperMankind:

到 ObservableObject
class ViewModel: Mankind {
    
}