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

SwiftUI如何向子视图传递可变@FocusState并解决赋值报错问题

SwiftUI 子视图修改父视图传入FocusState报错解决方案

错误原因

  • 子视图中声明的isEditing是FocusState<Bool>.Binding类型,并非Bool值本身,直接给该类型变量赋值Bool值会触发类型不匹配错误
  • SwiftUI的View结构体默认是不可变的,直接修改普通存储属性会触发self is immutable错误,只有通过属性包装器修饰的属性、或修改Binding类型的wrappedValue才允许修改值

解决方案

方案1:保留现有声明,修改赋值逻辑

仅需将Button的点击事件赋值逻辑改为访问wrappedValue即可:

struct ChildView: View {
    @Binding var text: String
    var isEditing: FocusState<Bool>.Binding
    
    init(_ text: Binding<String>, _ isEditing: FocusState<Bool>.Binding) {
        self._text = text
        self.isEditing = isEditing
    }
    
    var body: some View {
        TextField("Username", text: $text)
            .focused(isEditing)
        
        Button("Click me!") {
            // 访问Binding包裹的真实值进行修改
            isEditing.wrappedValue = false
        }
    }
}

方案2:使用更符合SwiftUI惯例的@Binding声明

直接在子视图用@Binding修饰Bool类型即可,无需单独声明FocusState<Bool>.Binding类型,写法更统一。父视图不需要做任何修改,仍传入$isEditing(@FocusState的前缀$会自动生成Binding<Bool>类型),子视图修改为如下写法:

struct ChildView: View {
    @Binding var text: String
    // 直接用@Binding声明Bool类型即可
    @Binding var isEditing: Bool
    
    init(_ text: Binding<String>, _ isEditing: Binding<Bool>) {
        self._text = text
        self._isEditing = isEditing
    }
    
    var body: some View {
        TextField("Username", text: $text)
            // 传入当前属性的Binding即可
            .focused($isEditing)
        
        Button("Click me!") {
            // 直接赋值即可,不需要访问wrappedValue
            isEditing = false
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:06:07