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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:36:07