You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI表单复用失效:SecondView无法输入内容

问题原因与解决方案

核心问题

你的代码里,FirstView用@StateObject创建了MainViewModel实例,但没有将这个实例注入到视图环境中,导致SecondView的@EnvironmentObject无法获取到同一个ViewModel实例——要么环境中没有对应实例导致隐式创建临时对象,要么拿到的是和FirstView无关的新实例,所以输入内容无法同步,出现输入后立即消失的情况。

修复步骤与代码示例

方案1:在FirstView中注入环境(适用于仅在FirstView子视图链中共享)

修改FirstView,将创建的ViewModel通过.environmentObject()注入到环境,确保后续子视图能拿到同一个实例:

class MainViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = ""
}

struct FirstView : View {
    // 仅在源头用@StateObject创建一次ViewModel
    @StateObject private var mainViewModel = MainViewModel()
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("姓名", text: $mainViewModel.name)
                TextField("年龄", text: $mainViewModel.age)
                // 导航到SecondView,此时SecondView会继承环境中的ViewModel
                NavigationLink("进入第二个视图", destination: SecondView())
            }
        }
        // 关键:将ViewModel注入当前视图的环境
        .environmentObject(mainViewModel)
    }
}

struct SecondView : View {
    // 直接从环境中获取共享的ViewModel实例
    @EnvironmentObject private var mainViewModel: MainViewModel
    
    var body: some View {
        Form {
            TextField("姓名", text: $mainViewModel.name)
            TextField("年龄", text: $mainViewModel.age)
        }
    }
}

方案2:在App入口注入环境(适用于全局所有视图共享)

如果需要整个App共享同一个ViewModel,可以在App的根视图注入:

@main
struct YourApp: App {
    // 在App级别创建并持有ViewModel实例
    @StateObject private var mainViewModel = MainViewModel()
    
    var body: some Scene {
        WindowGroup {
            FirstView()
                // 注入到全局环境
                .environmentObject(mainViewModel)
        }
    }
}

// 此时FirstView不需要再创建ViewModel,直接从环境获取
struct FirstView : View {
    @EnvironmentObject private var mainViewModel: MainViewModel
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("姓名", text: $mainViewModel.name)
                TextField("年龄", text: $mainViewModel.age)
                NavigationLink("进入第二个视图", destination: SecondView())
            }
        }
    }
}

关键注意事项

  • @StateObject仅用于ViewModel的创建源头,确保实例被正确持有,不要在多个视图中重复用它创建实例。
  • @EnvironmentObject用于在子视图中获取已注入环境的实例,使用前必须确保父级视图已经完成环境注入,否则会触发运行时崩溃。
  • 所有需要共享ViewModel的视图,必须处于同一个环境注入的视图链中,才能拿到同一个实例。

内容的提问来源于stack exchange,提问作者EN_Tech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:15:36