SwiftUI中动态创建的TextField如何在外部视图获取输入值?
解决方案
问题根源在于你的Input视图使用@State存储输入值,这是子视图的局部状态,无法与外部数据源双向同步。要实现外部视图获取输入值,需要通过状态提升+双向绑定来解决,具体步骤如下:
1. 修改Input视图,使用@Binding替代@State
将子视图的局部状态改为从外部传入的绑定,确保输入值能同步回父视图:
struct Input: View { var title: String @Binding var value: String // 替换@State为@Binding,实现双向绑定 var disableInputMode: Bool = true var body: some View { VStack { Text(title) .frame(maxWidth: .infinity, alignment: .leading) .foregroundColor(Color("SecondaryTextColor")) TextField("", text: $value) .disabled(disableInputMode) .frame(maxWidth: .infinity, alignment: .leading) Divider() } .padding() } }
2. 确保数据源支持双向绑定
根据你的数据模型类型,选择对应的实现方式:
情况一:数据模型为struct(推荐)
如果你的DetailDatum是值类型,需要让它遵循Identifiable,并在ViewModel中用@Published维护可变数组:
// 定义数据模型 struct DetailDatum: Identifiable { let id = UUID() var title: String var detail: String // 改为非可选类型,避免强制解包 } // 定义ViewModel class DetailsViewModel: ObservableObject { @Published var details: [DetailDatum] = [] // @Published自动通知视图更新 }
然后在父视图中,通过ForEach的绑定形式传递数据:
@ObservedObject var detailsViewModel: DetailsViewModel // 或@StateObject(iOS 14+) ScrollView { VStack { // 使用$绑定数组元素,直接传递detail的绑定给Input ForEach($detailsViewModel.details) { $datum in Input(title: datum.title, value: $datum.detail) } }.frame(maxWidth: .infinity) .padding() }.background(Color("Light")) .cornerRadius(25) .padding()
情况二:数据模型为class
如果你的DetailDatum是引用类型,让它遵循ObservableObject并使用@Published标记detail属性:
// 定义数据模型 class DetailDatum: Identifiable, ObservableObject { let id = UUID() var title: String @Published var detail: String // @Published监听属性变化 init(title: String, detail: String) { self.title = title self.detail = detail } } // 定义ViewModel class DetailsViewModel: ObservableObject { @Published var details: [DetailDatum] = [] }
父视图中传递绑定的方式略有不同:
@ObservedObject var detailsViewModel: DetailsViewModel ScrollView { VStack { ForEach(detailsViewModel.details) { datum in // 通过datum.$detail获取绑定 Input(title: datum.title, value: datum.$detail) } }.frame(maxWidth: .infinity) .padding() }.background(Color("Light")) .cornerRadius(25) .padding()
3. 关键注意事项
- 避免使用
datum.detail!强制解包,建议将模型中的detail设为非可选类型,初始值为空字符串,防止运行时崩溃。 - 确保ViewModel被正确注入到父视图中(如通过
@ObservedObject或@StateObject),否则数据变化无法触发视图更新。
内容的提问来源于stack exchange,提问作者Ron Weasley
相关产品推荐
相关产品推荐

