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

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。

修复步骤

  1. 修正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() 
                }
            }
        }
    }
}
  1. 优化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:35:45