Fer*_*and 3 xcode swift swiftui swiftui-navigationlink
我有这样的结构
contentView {
navigationView{
foreach {
NavigationLink(ViewA(id: id))
}
}
}
Run Code Online (Sandbox Code Playgroud)
///其中视图A包含一个请求触发器在视图中出现
struct ViewA: View {
@State var filterString: String = ""
var id: String!
@ObservedObject var model: ListObj = ListObj()
init(id: String) {
self.id = id
}
var body: some View {
VStack {
SearchBarView(searchText: $filterString)
List {
ForEach(model.items.filter({ filterString.isEmpty || $0.id.contains(filterString) || $0.name.contains(filterString) }), id: \.id) { item in
NavigationLink(destination: ViewB(id: item.id)) {
VStack {
Text("\(item.name) ")
}
}
}
}
}
.onAppear {
self.model.getListObj(id: self.id) //api request, fill data and call objectWillChange.send()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
ViewB和ViewB的代码一样,Receive id,store,request api来采集数据。
但是 viewB 列表没有被刷新。我也注意到viewB的
Run Code Online (Sandbox Code Playgroud)@ObservedObject var model: model = model()
被多次实例化
调试时,我发现每个 navigationLink 实例在它被触发之前都是目的地。这通常不是问题,
但就我而言,我觉得 ViewB 模型被实例化了 2 次,而我的 onApear 调用了错误的模型,这是 self.objectWillChange.send() 不刷新我的视图的原因
这里有两个问题:
body.NavigationLink不是懒惰。ListObj每次调用时都会实例化一个新的ViewA.init(...)。 ObservedObject 不工作一样@State在整个屏幕上的生命周期,其中SwiftUI保持它精心为您跟踪。SwiftUI 假设一个的最终所有权@ObservedObject存在于View它所使用的某个级别之上。
换句话说,你应该几乎总是避免诸如@ObservedObject var myObject = MyObservableObject().
(注意,即使你这样做了,@State var model = ListObj()它每次都会被实例化。但是因为它是@StateSwiftUI,它会在body被调用之前用原始实例替换新实例。)
除此之外,NavigationLink就是不偷懒。每次实例化时,NavigationLink都会传递一个新实例ViewA化的ListObj.
所以对于初学者来说,你可以做的一件事就是LazyView延迟实例化,直到NavigationLink.destination.body真正被调用:
// Use this to delay instantiation when using `NavigationLink`, etc...
struct LazyView<Content: View>: View {
var content: () -> Content
var body: some View {
self.content()
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以做NavigationLink(destination: LazyView { ViewA() })并且实例化ViewA将被推迟到destination实际显示。
只要它是层次结构中的顶视图,简单地使用LazyView就可以解决您当前的问题,就像您将其推入 a或呈现它一样。NavigationView
但是,这就是@user3441734 评论的用武之地。您真正需要做的是将所有权保留model在您之外的某个地方,View因为在#1 中进行了解释。
如果您的对象@ObservedObject被多次初始化,那是因为每次状态发生变化时,对象的所有者都会被刷新并重新创建。@StateObject如果您的应用程序是 iOS 14 及以上版本,请尝试使用。它可以防止视图刷新时重新创建对象。
https://developer.apple.com/documentation/swiftui/stateobject
当视图创建自己的 @ObservedObject 实例时,每次丢弃和重绘视图时都会重新创建它。相反,当视图重绘时,@State 变量将保留其值。@StateObject 是 @ObservedObject 和 @State 的组合 - 即使在视图被丢弃和重绘后,ViewModel 的实例也将被保留和重用
SwiftUI 中 ObservedObject 和 StateObject 有什么区别
| 归档时间: |
|
| 查看次数: |
1603 次 |
| 最近记录: |