从我在视图中自己实例化对象时所读到的内容中,您应该使用@StateObject
而不是@ObservedObject
. 因为显然,如果您使用@ObservedObject
SwiftUI,SwiftUI 可能会随时决定将其丢弃并稍后重新创建它,这对于某些对象来说可能会很昂贵。但是如果你改用@StateObject
它,那么显然 SwiftUI 知道不要把它扔掉。
我理解正确吗?
我的问题是,如何将其@StateObject
传达给 SwiftUI?我问的原因是因为我制作了自己的 propertyWrapper,它将视图的属性连接到 firebase firestore 集合,然后开始监听实时快照。这是一个看起来像的例子:
struct Room: Model {
@DocumentID
var id: DocumentReference? = nil
var title: String
var description: String
static let collectionPath: String = "rooms"
}
struct MacOSView: View {
@Collection({ $0.order(by: "title") })
private var rooms: [Room]
var body: some View {
NavigationView {
List(rooms) { room in
NavigationLink(
destination: Lazy(ChatRoom(room))
) {
Text(room.title)
}
}
}
}
}
内部的闭包@Collection
是可选的,但可用于为集合构建更精确的查询。
现在这很好用。代码很有表现力,我得到了很好的实时更新数据。您可以看到,当用户单击房间标题时,导航视图将导航到该聊天室。聊天室是显示该房间中所有消息的视图。这是该代码的简化视图:
struct ChatRoom: View {
@Collection(wait: true)
private var messages: [Message]
// I'm using (wait: true) to say "don't open a connection just yet,
// because I need to give you more information that I can't give you yet"
// And that's because I need to give @Collection a query
// based on the room id, which I can only do in the initializer.
init(_ room: Room) {
_messages = Collection { query in
query
.whereField("room", isEqualTo: room.id!)
.order(by: "created")
}
}
var body: some View {
List(messages) { message in
MessageBubble(message: message)
}
}
}
但我注意到,每次用户以任何方式与 UI 交互时,SwiftUI 都会初始化一个新的消息集合。就像即使单击输入框以使其获得焦点一样。这是一个巨大的内存泄漏。我不明白为什么会发生这种情况,但是有没有办法告诉 SwiftUI 只初始化@Collection
一次,就像它一样@StateObject
?