我无法在主视图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
修改它像一个对象。