macOS 13.3中SwiftUI Picker的onChange无法更新FocusState为nil
问题解决办法
你的代码存在几个关键细节错误,导致FocusState无法正确重置:
1. FocusState类型匹配错误
你定义的@FocusState var isFocused: MyView.Field?中,MyView.Field是无效类型——枚举Field属于当前的MyTestView结构体,应改为Field?。
2. 缺失TextField的绑定变量
代码里的myTextVar和myTextVar2未声明为@State变量,导致TextField无法正常工作,也会间接影响焦点状态的绑定逻辑。
3. onChange监听对象不合理
你监听的是myPickerVar ?? "",但myPickerVar本身是可选字符串,直接监听myPickerVar能更准确捕获值的变化,避免空值处理带来的逻辑偏差。
修正后的完整代码
struct MyTestView: View { enum Field: Hashable { case field1 case field2 } @State private var myArray = ["One", "Two", "Three"] @State private var myPickerVar: String? = "One" @FocusState var isFocused: Field? // 修正类型匹配 @State private var myTextVar = "" // 补上缺失的绑定变量 @State private var myTextVar2 = "" // 补上缺失的绑定变量 var body: some View { VStack { Picker(selection: $myPickerVar.animation()) { ForEach(myArray, id: \.self) { option in Text(option) .tag(Optional(option)) } } label: { Text("My Picker") } .onChange(of: myPickerVar) { newValue in isFocused = nil // 用@MainActor包裹确保状态更新后再执行后续代码 Task { @MainActor in print("Focused: \(String(describing: isFocused))") // 这里执行你的其他业务代码 } } TextField("", $myTextVar) .focused($isFocused, equals: .field1) .border(.red, width: isFocused == .field1 ? 1 : 0) // 直观显示焦点状态 TextField("", $myTextVar2) .focused($isFocused, equals: .field2) .border(.red, width: isFocused == .field2 ? 1 : 0) // 直观显示焦点状态 } .padding() } }
额外说明
- SwiftUI的状态更新是异步的,直接在
isFocused = nil后打印可能无法获取最新值,用@MainActor的Task包裹后续代码,能确保在状态更新完成后执行。 - 给TextField添加边框可以直观看到焦点是否被移除,方便测试验证。
内容的提问来源于stack exchange,提问作者kittonian
相关产品推荐
相关产品推荐

