Ios 迅捷不';t使用嵌套导航链接目标中的ObservedObject更新UI
我目前有一个从API获取数据的应用程序,在根视图(我们称之为Home)中,一切正常,在第二个视图(我们称之为用户视图)中,一切正常,但现在在第三个视图(团队视图)中,仅此视图的Ios 迅捷不';t使用嵌套导航链接目标中的ObservedObject更新UI,ios,swift,swiftui,Ios,Swift,Swiftui,我目前有一个从API获取数据的应用程序,在根视图(我们称之为Home)中,一切正常,在第二个视图(我们称之为用户视图)中,一切正常,但现在在第三个视图(团队视图)中,仅此视图的ObservedObject不工作 最奇怪的是,如果用户直接导航到团队视图,那么所有事情都会按照预期工作 每个视图都有自己的观察对象加载的数据只属于该视图 每个视图之间的导航由NavigationLink 下面是一个我如何进行加载和导航的示例 struct HomeView:View{ @ObservedObject va
ObservedObject
不工作
最奇怪的是,如果用户直接导航到团队视图,那么所有事情都会按照预期工作
每个视图都有自己的观察对象
加载的数据只属于该视图
每个视图之间的导航由NavigationLink
下面是一个我如何进行加载和导航的示例
struct HomeView:View{
@ObservedObject var viewModel=HomeViewModel()
var body:一些观点{
VStack{
导航链接(目的地:UserView(userId:viewModel.userId))
导航链接(目的地:TeamView(teamId:viewModel.teamId))
}
}
}
struct TeamView:View{
@ObservedObject var viewModel=TeamViewModel()
@状态变量teamId:String=“”
var body:一些观点{
文本(viewModel.name)
.onAppear(){viewModel.loadData(id:teamId)}
}
}
结构UserView:View{
@ObservedObject var viewModel=UserViewModel()
@状态变量userId:String=“”
var body:一些观点{
VStack{
文本(viewModel.name)
导航链接(目的地:TeamView(teamId:viewModel.teamId))
}
.onAppear(){viewModel.loadData(id:userId)}
}
}
从该示例中可以看到,加载数据的函数位于视图模型中,并且在视图出现时加载
一切正常,但当我到达堆栈中的第三级时,数据不会在视图中更新。我原以为可能是线程,但当获取完成时,我正在使用DispatchQueue.main.async
模型上所有必要的变量都标记为@Published
总之,以下流程是有效的
HomeView -> TeamView
HomeView -> UserView
但在最后一个视图中,它确实加载了数据,但不更新视图
HomeView -> UserView -> TeamView
我复制了您的代码行为,问题在于快速导航。发生了什么事 如果你愿意
HomeView [tap] -> UserView -> [wait for user loaded] -> TeamView // no issue
但你知道
HomeView [tap] -> UserView [tap] -> TeamView // got defect
该缺陷是因为加载数据时,UserView
在后台更新,所以重建了body
,所以重新创建了链接,所以重建了TeamView
,但是没有调用。onAppear
,因为这样的视图已经出现在屏幕上
(我不确定这是否是SwiftUI错误,因为这种行为是有逻辑的)
所以这里有一个解决这个问题的方法。使用Xcode 11.5b进行测试
struct TeamView: View {
@ObservedObject var viewModel = TeamViewModel()
var teamId: String // << state is not needed
init(teamId: String) {
self.teamId = teamId
viewModel.loadData(id: teamId) // initiate load here !!
}
var body: some View {
Text(viewModel.name)
}
}
struct UserView: View {
@ObservedObject var viewModel = UserViewModel()
@State var userId: String = ""
var body: some View {
VStack {
Text(viewModel.name)
// used DeferView to avoid in-advance constructions
NavigationLink(destination: DeferView { TeamView(teamId: viewModel.teamId) })
}
.onAppear() { viewModel.loadData(id: userId) }
}
}
struct TeamView:View{
@ObservedObject var viewModel=TeamViewModel()
var-teamId:String//非常感谢,它工作得非常好。但是(在我的代码中)只有在加载UserView completed时才能导航,否则它就会知道teamId。无论如何,您的解决方案工作得非常好。Thx很多我已经在胡思乱想了