Áko*_*vai 6 ios swift swiftui ios16 swiftui-navigationstack
我正在尝试使我的应用程序适应 IOS 16 中引入的新功能。当我的一个视图中NavigationStack有一个变量时,我最终出现了奇怪的行为。@StateObject
当我导航(使用 new修饰符)到具有该对象的块.navigationDestination()的新视图时,该对象将运行两次。@StateObjectinit()
视图的主体如下所示:
VStack {
Text("Param: \(intParam) and \(viewModel.someData)")
Button("Do Something") {
viewModel.buttonTapped()
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除 Button 元素,则init()只会@StateObject运行一次。
如果我使用旧NavigationLink(title:destination:)元素导航到新页面,它将运行一次@StateObject init()。
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
NavigationLink(value: 16) {
Text("Tap Me (IOS 16)")
}
NavigationLink("Tap Me (Older)") {
Page2(intParam: 45)
}
}
.navigationDestination(for: Int.self) { i in
Page2(intParam: i)
}
.navigationTitle("Navigation")
}
}
}
struct Page2: View {
@StateObject var viewModel = ViewModel()
let intParam: Int
init(intParam: Int) {
self.intParam = intParam
print("Page2 view created")
}
var body: some View {
VStack {
Text("Param: \(intParam) and \(viewModel.someData)")
Button("Do Something") {
viewModel.buttonTapped()
}
}
}
}
extension Page2 {
@MainActor class ViewModel: ObservableObject {
@Published var someData = "something"
init() {
print("Page2 viewmodel created")
}
func buttonTapped() {
print("do something")
}
}
}
Run Code Online (Sandbox Code Playgroud)
您知道这种行为的原因吗?
这不是一个错误,但它肯定会让开发人员感到困惑。当使用NavigationStack的destination方法导航到其他视图时,SwiftUI确实可能会多次调用navigationDestination内部的闭包代码(大部分是两次)。但是,它使用上次调用的结果来生成下一层视图。这意味着无论您创建多少个 StateObject 实例,只有最后生成的实例才会在目标视图中使用。其他实例将被自动销毁。
准确的说,这并不是创建同一个StateObject的多个实例,而是执行多次创建视图的操作,只保留最后一次创建的结果。
作为开发人员,我们只需要知道,当访问下一层视图时,您的 StateObject 实例是唯一的,并且在导航到更多层时仍然保持唯一。
这也从另一个角度告诉开发者不要在init中进行任何昂贵的操作,而是将此类操作放在onAppear或task中。
至于回复中提到的onAppear可能会被多次调用(返回视图时)的问题,可以通过添加@State标志来解决。
| 归档时间: |
|
| 查看次数: |
999 次 |
| 最近记录: |