SwiftUI iOS15中如何结合Field枚举使用FocusState检测TextField失焦
解决方案
完全可以基于你现有Field枚举类型的focusedField实现失焦监听,不需要额外新增Bool类型的@FocusState破坏原有的焦点跳转逻辑,方案如下:
核心实现思路
直接监听全局focusedField的状态变化,判断上一次聚焦的是目标字段、且当前不再聚焦该字段时,就触发对应的失焦逻辑,只需要新增一个状态变量暂存上一次的聚焦状态用于对比即可。
完整代码示例如下:
struct CustomerForm: View { @ObservedRealmObject var customer: Customer // 原有逻辑保留 @FocusState private var focusedField: Field? enum Field: Hashable { case nameFirst case nameLast case notes case phone case email case addrCity case addrStreet1 case addrStreet2 case addrPostalCode } // 新增:暂存上一次的聚焦字段 @State private var previousFocusedField: Field? var body: some View { NavigationView { Form { // 原有表单代码完全保留 TextField( "City", text: $customer.addrCity, onCommit: { focusedField = .addrPostalCode } ) .focused($focusedField, equals: .addrCity) .submitLabel(.next) TextField( "Postal Code", text: $customer.addrPostalCode ) .focused($focusedField, equals: .addrPostalCode) } // 新增全局监听聚焦状态变化 .onChange(of: focusedField) { newValue in // 邮编字段失焦判断 if previousFocusedField == .addrPostalCode, newValue != .addrPostalCode { // 这里放你原本要在输入变化时执行的逻辑 print("邮编字段失焦,当前值:\(customer.addrPostalCode)") } // 可以扩展任意字段的失焦监听,比如监听城市字段失焦: // if previousFocusedField == .addrCity, newValue != .addrCity { // 城市字段失焦逻辑 // } // 更新上一次聚焦状态 previousFocusedField = newValue } } } }
简化方案
如果你只需要监听个别字段的失焦,不需要对比跳转来源,可以省略previousFocusedField变量,直接简化判断:
.onChange(of: focusedField) { newValue in guard newValue != .addrPostalCode else { return } // 聚焦状态离开邮编字段时触发逻辑 }
这种写法在绝大多数常规场景下都可以正常运行。
内容的提问来源于stack exchange,提问作者pulpfree
相关产品推荐
相关产品推荐

