SwiftUI 4中NavigationLink触发.navigationDestination目标两次问题求助
这个问题是SwiftUI视图渲染机制导致的:navigationDestination的内容闭包可能在视图更新时被多次执行,直接在闭包内初始化ObservableObject会造成重复实例化。以下是几种可行的解决思路:
方案一:用@StateObject管理Model生命周期
将SubView中的@ObservedObject改为@StateObject,并把Model的初始化移到SubView内部,确保实例在视图生命周期内仅创建一次。
修改后的代码:
struct Content: View { var body: some View { NavigationStack { ScrollView { VStack { ForEach(0..<10) { number in NavigationLink(value: number) { Text("\(number)") } } } }.navigationDestination(for: Int.self) { value in SubView(value: value) } } } } class Model: ObservableObject { @Published var value: Int init(value: Int) { print("Init for value \(value)") self.value = value // 在这里执行网络请求、计算等逻辑 } } struct SubView: View { let value: Int @StateObject private var model: Model init(value: Int) { self.value = value self._model = StateObject(wrappedValue: Model(value: value)) } var body: some View { Text("\(model.value)") } }
@StateObject会绑定到视图的生命周期,即使视图因父状态变化重新渲染,也不会重新初始化Model实例。
方案二:提前缓存Model实例
在父视图中提前创建并缓存每个对应值的Model,避免navigationDestination闭包重复初始化。
示例代码:
struct Content: View { @State private var cachedModels: [Int: Model] = [:] var body: some View { NavigationStack { ScrollView { VStack { ForEach(0..<10) { number in NavigationLink(value: number) { Text("\(number)") } .onAppear { // 提前初始化并存入缓存 if cachedModels[number] == nil { cachedModels[number] = Model(value: number) } } } } }.navigationDestination(for: Int.self) { value in SubView(model: cachedModels[value]!) } } } } // Model和SubView保持原定义(SubView使用@ObservedObject)
通过onAppear提前初始化Model并缓存,navigationDestination直接复用已有实例,从根源避免重复创建。
方案三:在Model内部限制逻辑执行次数
如果无法修改视图结构,可以在Model内部添加执行标志,确保网络请求、计算等核心逻辑仅运行一次:
class Model: ObservableObject { @Published var value: Int private var hasExecutedSetup = false init(value: Int) { print("Init for value \(value)") self.value = value } func runSetupLogic() { guard !hasExecutedSetup else { return } hasExecutedSetup = true // 在这里执行网络请求、计算等逻辑 } } struct SubView: View { @ObservedObject var model: Model var body: some View { Text("\(model.value)") .onAppear { model.runSetupLogic() } } }
即使Model被初始化两次,核心逻辑也只会在第一次onAppear时执行,避免重复操作。
内容的提问来源于stack exchange,提问作者Fleet Phil
相关产品推荐
相关产品推荐

