为何@ObservedObject在NavigationLink中复用模型,@StateObject却不会?
问题现象
在iPhone模拟器中运行以下代码时,通过NavigationLink跳转至ScorePlate后,会复用上次的Model实例:
import SwiftUI struct ContentView: View { @State private var showRealName = false var body: some View { NavigationView { VStack { Button("Toggle Name") { showRealName.toggle() } Text("Current User: \(showRealName ? "Wei Wang" : "onevcat")") NavigationLink("Next", destination: ScorePlate().padding(.top, 20)) } } } } class Model: ObservableObject { init() { print("Model Created") } @Published var score: Int = 0 } struct ScorePlate: View { @ObservedObject var model = Model() @State private var niceScore = false var body: some View { let _ = print("ScorePlate") VStack { Button("+1") { if model.score > 3 { niceScore = true } model.score += 1 } Text("Score: \(model.score)") Text("Nice? \(niceScore ? "YES" : "NO")") ScoreText(model: model).padding(.top, 20) } } } struct ScoreText: View { @ObservedObject var model: Model var body: some View { if model.score > 10 { return Text("Fantastic") } else if model.score > 3 { return Text("Good") } else { return Text("Ummmm...") } } }
但将ScorePlate中的模型声明从@ObservedObject var model = Model()改为@StateObject var model = Model()后,复用现象消失。这和“@StateObject会复用实例、@ObservedObject会每次创建”的认知相反,原因如下:
核心原因解析
纠正认知偏差:
@StateObject的作用是让View拥有并管理ObservableObject的生命周期,它会保证在View的整个生命周期内,对象只被初始化一次。@ObservedObject是用来观察外部传入的ObservableObject,它本身不负责对象的创建和生命周期管理——在View内部直接初始化@ObservedObject的写法,其实不符合它的设计初衷。
@ObservedObject出现复用的原因:
SwiftUI的NavigationLink导航栈机制会缓存已push过的View实例。第一次跳转时创建的ScorePlate实例会被保留在导航栈中,当你返回再重新跳转时,即使ContentView的body因showRealName变化重新计算、生成了新的ScorePlate()对象,导航栈依然会复用之前缓存的旧ScorePlate实例,它内部的model自然也跟着被复用了。@StateObject不复用的原因:
当使用@StateObject时,每个ScorePlate实例都拥有独立的model对象。当你从导航栈返回再重新跳转时,NavigationLink会创建全新的ScorePlate实例(而非复用旧实例),新实例的@StateObject会触发Model的初始化,因此不会出现复用现象。
内容的提问来源于stack exchange,提问作者ximmyxiao
相关产品推荐
相关产品推荐

