SwiftUI中TextField点击时editMode首次意外切换为false的修复问题
问题
我有一个名为editMode的布尔值,用来判断用户是否能编辑当前页面信息。当把它切换为true后,首次点击TextField时这个布尔值会被切回false;后续点击TextField就没有这个问题,请问该怎么修复这个异常?
相关代码
RecipeControllerModal
struct RecipeControllerModal: View { @Environment(\.dismiss) var dismiss // 关闭视图 @ObservedObject var rm = RecipeLogic() @ObservedObject var ema = EditModeActive() // 传递到下一个视图 var body: some View { NavigationView{ VStack{ VStack{ RecipeDashHeader(ema: ema) // 传递editMode .padding() } } } } }
RecipeDashHeader(TextField视图)
struct RecipeDashHeader: View { @State var recipeName = "" @ObservedObject var ema: EditModeActive @ViewBuilder var body: some View { if ema.editMode { VStack{ TextField(recipeName, text: $recipeName) .foregroundColor(!ema.editMode ? Color.black : Color.red) .font(.title2) .multilineTextAlignment(.center) .padding() .onChange(of: recipeName, perform: { _ in ema.recipeTitle = recipeName }) } } } }
发布的EditMode变量
class EditModeActive: ObservableObject { @Published var editMode: Bool = false @Published var recipeTitle = "" }
解决方案
问题原因
RecipeControllerModal中使用@ObservedObject声明并直接初始化ema,但@ObservedObject的生命周期依赖外部传入,当视图因点击TextField触发刷新时,会重新创建EditModeActive实例,导致editMode被重置为初始值false。
修复步骤
- 修正ObservableObject的生命周期管理
将RecipeControllerModal中的@ObservedObject改为@StateObject,确保EditModeActive实例在视图生命周期内仅初始化一次,不会随视图刷新重置状态:
struct RecipeControllerModal: View { @Environment(\.dismiss) var dismiss // 关闭视图 @ObservedObject var rm = RecipeLogic() @StateObject var ema = EditModeActive() // 改为@StateObject var body: some View { NavigationView{ VStack{ VStack{ RecipeDashHeader(ema: ema) // 传递editMode .padding() } } } } }
- 优化TextField的初始化与状态同步
RecipeDashHeader中TextField的第一个参数应为占位文本而非绑定变量,同时在初始化时同步ema.recipeTitle到本地状态,避免初始值异常:
struct RecipeDashHeader: View { @State var recipeName: String @ObservedObject var ema: EditModeActive // 初始化时同步外部状态到本地 init(ema: EditModeActive) { self.ema = ema self._recipeName = State(initialValue: ema.recipeTitle) } @ViewBuilder var body: some View { if ema.editMode { VStack{ TextField("输入食谱名称", text: $recipeName) .foregroundColor(ema.editMode ? .red : .black) .font(.title2) .multilineTextAlignment(.center) .padding() .onChange(of: recipeName) { newValue in ema.recipeTitle = newValue } } } else { // 非编辑模式下展示食谱标题 Text(ema.recipeTitle) .foregroundColor(.black) .font(.title2) .multilineTextAlignment(.center) .padding() } } }
修改完成后,editMode状态会稳定保留,首次点击TextField时不会再被意外重置。
内容的提问来源于stack exchange,提问作者Swink
相关产品推荐
相关产品推荐

