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

SwiftUI中编辑完成后为TextField追加‘kg’无效果问题咨询

SwiftUI TextField 编辑完成后无法添加“kg”后缀问题

问题描述

我有一个由List行组成的SwiftUI View,希望在用户完成TextField编辑后,为每个输入框添加‘kg’后缀。当前weightEntries数组能正确赋值(可通过打印语句验证),但TextField并未在末尾添加“kg”。以$textFieldInputs作为数据源,为何onCommit触发时文本没有变化?

示例代码:

import SwiftUI

struct minworkoutview: View {
    @State private var textFieldInputs: [String] = Array(repeating: "", count: 5)
    @State private var weightEntries = [20, 20, 20, 20, 20]
    
    var body: some View {
        List {
            ForEach(0..<5, id: \.self) { index in
                TextField("Enter Weight", text: $textFieldInputs[index], onCommit: {
                    let weightString = textFieldInputs[index].trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: " kg", with: "")
                    if let newWeight = Double(weightString) {
                        weightEntries[index] = Int(newWeight * 1000)
                        textFieldInputs[index] = "\(newWeight) kg"
                        
                        print("\(weightEntries[index])")
                        
                    }
                    
                })
            }
        }
    }
}

struct minworkoutview_Preview: PreviewProvider {
    static var previews: some View {
        minworkoutview()
    }
}

问题原因

核心问题是SwiftUI TextField在onCommit触发时,内部仍持有编辑状态的文本引用。你在onCommit中直接修改textFieldInputs[index]的操作,会被TextField后续的内部状态同步逻辑覆盖,导致修改无法生效。

解决方案

方案1:延迟修改到下一个主队列循环

通过DispatchQueue.main.async把文本修改操作延迟到TextField完成内部状态更新后执行,避免被覆盖:

import SwiftUI

struct MinWorkoutView: View {
    @State private var textFieldInputs: [String] = Array(repeating: "", count: 5)
    @State private var weightEntries = [20, 20, 20, 20, 20]
    
    var body: some View {
        List {
            ForEach(0..<5, id: \.self) { index in
                TextField("Enter Weight", text: $textFieldInputs[index], onCommit: {
                    let weightString = textFieldInputs[index]
                        .trimmingCharacters(in: .whitespacesAndNewlines)
                        .replacingOccurrences(of: " kg", with: "")
                    if let newWeight = Double(weightString) {
                        weightEntries[index] = Int(newWeight * 1000)
                        // 延迟执行修改,避开TextField的内部状态同步
                        DispatchQueue.main.async {
                            textFieldInputs[index] = "\(newWeight) kg"
                        }
                        print("\(weightEntries[index])")
                    }
                })
            }
        }
    }
}

struct MinWorkoutView_Preview: PreviewProvider {
    static var previews: some View {
        MinWorkoutView()
    }
}

方案2:使用自定义绑定(更推荐)

自定义Binding将输入处理逻辑整合到值的setter中,不管用户是通过回车完成编辑还是失去焦点,都能自动处理后缀,更符合SwiftUI数据流逻辑:

import SwiftUI

struct MinWorkoutView: View {
    @State private var textFieldInputs: [String] = Array(repeating: "", count: 5)
    @State private var weightEntries = [20, 20, 20, 20, 20]
    
    var body: some View {
        List {
            ForEach(0..<5, id: \.self) { index in
                // 自定义Binding,统一处理输入清洗和后缀添加
                let customBinding = Binding(
                    get: { textFieldInputs[index] },
                    set: { rawInput in
                        let cleanedInput = rawInput
                            .trimmingCharacters(in: .whitespacesAndNewlines)
                            .replacingOccurrences(of: " kg", with: "")
                        if let weightValue = Double(cleanedInput) {
                            weightEntries[index] = Int(weightValue * 1000)
                            textFieldInputs[index] = "\(weightValue) kg"
                        } else {
                            // 输入无效时保留原始内容(或根据需求清空)
                            textFieldInputs[index] = rawInput
                        }
                    }
                )
                
                TextField("Enter Weight", text: customBinding)
            }
        }
    }
}

struct MinWorkoutView_Preview: PreviewProvider {
    static var previews: some View {
        MinWorkoutView()
    }
}

说明

方案2的自定义Binding方式更可靠,它直接介入TextField的数据流,确保每次输入值变更时都能触发处理逻辑,覆盖所有编辑结束的场景(不仅仅是onCommit触发的回车操作)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:10:37