我一直在为SwiftUI问题苦苦挣扎数小时。
这是我的问题的简化示例:
class Parent: ObservableObject {
@Published var children = [Child()]
}
class Child: ObservableObject {
@Published var name: String?
func loadName() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Async task here...
self.objectWillChange.send()
self.name = "Loaded name"
}
}
}
struct ContentView: View {
@ObservedObject var parent = Parent()
var body: some View {
Text(parent.children.first?.name ?? "null")
.onTapGesture {
self.parent.objectWillChange.send()
self.parent.children.first?.loadName() // does not update
}
}
}
我有一个ObservableObject(父级),它存储着@Published的ObservableObjects(子级)数组。
问题在于,当通过对数组中一个对象的异步任务更改name属性时,视图不会更新。
你有什么主意吗?
非常感谢 尼古拉斯
答案 0 :(得分:1)
我会说这是设计问题。请在下面找到仅使用SwiftUI功能且不需要任何解决方法的首选方法。关键思想是“视图-视图模型”的分解和显式依赖注入。
通过Xcode 11.4 / iOS 13.4测试
class Parent: ObservableObject {
@Published var children = [Child()]
}
class Child: ObservableObject {
@Published var name: String?
func loadName() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Async task here...
self.name = "Loaded name"
}
}
}
struct FirstChildView: View {
@ObservedObject var child: Child
var body: some View {
Text(child.name ?? "null")
.onTapGesture {
self.child.loadName()
}
}
}
struct ParentContentView: View {
@ObservedObject var parent = Parent()
var body: some View {
// just for demo, in real might be conditional or other UI design
// when no child is yet available
FirstChildView(child: parent.children.first ?? Child())
}
}
答案 1 :(得分:0)
这种替代方法对我有用:
class Parent: ObservableObject {
@Published var children = [Child()]
}
class Child: ObservableObject {
@Published var name: String?
func loadName(handler: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Async task here...
self.name = UUID().uuidString // just for testing
handler()
}
}
}
struct ContentView8: View {
@ObservedObject var parent = Parent()
var body: some View {
Text(parent.children.first?.name ?? "null").padding(10).border(Color.black)
.onTapGesture {
self.parent.children.first?.loadName(){
self.parent.objectWillChange.send()
}
}
}
}
答案 2 :(得分:0)
确保您的孩子模型是struct
!类无法正确更新用户界面。