@StateObject在init()例程中的问题



我无法在主视图init()例程中正确初始化@StateObject变量。看起来好像对象在每次修改时都被重新初始化,并在ui准备好时最终未被填充。下面是代码:


import SwiftUI
class Node: Identifiable {
var id = UUID()
var x = 0.0
var y = 0.0
func toString() -> String {
return "(id):((x), (y))"
}
}
class Objects: ObservableObject {
@Published var nodes: [Node] = []
@Published var show: Bool = false

func addNode(_ node: Node) {
self.nodes.append(node)
print(self.nodes.count)
}

func toString() -> String {
var s = "Nodes: ((self.nodes.count))n"
for node in self.nodes {
s += node.toString() + "n"
}
return s
}
}
struct ContentView: View {
@StateObject var objects = Objects()

init() {
var node = Node()
node.x = 50
node.y = 200
print(node.toString())
objects.addNode(node)
node = Node()
node.x = 200
node.y = 100
print(node.toString())
objects.addNode(node)
objects.show.toggle()
print(objects.toString())
}

var body: some View {
Button("Add") {
let i = objects.nodes.count
let node = Node()
node.x = Double(i)
node.y = Double(i)
objects.addNode(node)
print(objects.toString())
}
.padding()
.foregroundColor(.white)
.background(.red)
}
}

控制台意外地显示了这个:


31042C43-103A-48F3-B926-47A5B2CB9610:(50.0, 200.0)
1
6B95D75C-8849-4840-AB0F-56BEED00D73F:(200.0, 100.0) 
1
Nodes: (0)

现在,按下"按钮,数组计数从1开始递增。

如果我从

改变变量的声明
@StateObject var objects = Objects()

@State var objects = Objects()

初始化按预期进行:

6A2A5EFF-1A7F-4995-B2D6-DC22537FB4D1:(50.0, 200.0)
1
A118917D-6635-4E4E-AED0-B865AF2DA81C:(200.0, 100.0)
2
Nodes: (2)
6A2A5EFF-1A7F-4995-B2D6-DC22537FB4D1:(50.0, 200.0)
A118917D-6635-4E4E-AED0-B865AF2DA81C:(200.0, 100.0)

和数组计数从3开始,当我按下"添加"按钮。

不幸的是,我需要跨视图共享对象,因此@StateObject是必需的。你能给我建议一个解决方案,解释为什么这个动作吗?

正如在评论中引用的,这里是一个固定的变体(在Xcode 13.4/iOS 15.5测试)

struct ContentView: View {
@StateObject var objects: Objects
init() {
let objects = Objects()   // << created
var node = Node()
node.x = 50
node.y = 200
print(node.toString())
objects.addNode(node)
node = Node()
node.x = 200
node.y = 100
print(node.toString())
objects.addNode(node)
objects.show.toggle()
print(objects.toString())
// Note: don't believe Apple's documentation about this initializer
// and those on SO who shout about it ;-)
_objects = StateObject(wrappedValue: objects)    // << here !!
}

对象不是共享数据所必需的。当传递给子View时,声明let为读访问,@Binding为写访问。如果参数与上次View作为init时不同,则调用body

尝试@State结构,使用mutating func修改它像一个对象。

最新更新