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

SwiftUI TextField清空后显示残留数字而非0值如何修复

问题描述

在两个使用.percent格式绑定Double类型变量a、b的TextField中分别输入数值(例如依次输入58、78),清空变量a对应的输入框内容后,切换到变量b对应的输入框时,a的输入框不会显示0值,反而残留显示数字5。
复现代码如下:

import SwiftUI

struct ContentView: View {
    @State var a = Double()
    @State var b = Double()

    var body: some View {
        HStack {
            Text("Number 1")
            TextField("Enter Number 1", value: $a, format: .percent)
        }
        HStack {
            Text("Number 2")
            TextField("Enter Number 2", value: $b, format: .percent)
        }
    }
}
问题原因

系统内置的.percent格式化器接收到空字符串输入时会解析失败,既不会更新绑定的Double值,也不会触发输入框文本重绘,最终导致输入内容、绑定值、UI显示三者不同步,出现字符残留。

修复方案

两种方案都可以实现清空输入、失去焦点后自动显示0值的效果,根据需求选择即可:

  • 方案1:最小改动适配,给现有TextField增加编辑状态监听,在编辑结束时通过显式赋值触发UI刷新
import SwiftUI

struct ContentView: View {
    @State var a = Double()
    @State var b = Double()

    var body: some View {
        VStack(spacing: 20) {
            HStack {
                Text("Number 1")
                TextField(
                    "Enter Number 1",
                    value: $a,
                    format: .percent,
                    onEditingChanged: { isEditing in
                        guard !isEditing else { return }
                        // 触发值更新,强制输入框重绘为绑定值对应的格式化文本
                        let temp = a
                        a = 0
                        a = temp
                    }
                )
            }
            HStack {
                Text("Number 2")
                TextField(
                    "Enter Number 2",
                    value: $b,
                    format: .percent,
                    onEditingChanged: { isEditing in
                        guard !isEditing else { return }
                        let temp = b
                        b = 0
                        b = temp
                    }
                )
            }
        }
        .padding()
    }
}
  • 方案2:自定义格式化器,从解析逻辑层面修复,复用性更高
    自定义支持空输入自动转0的百分比格式,空字符串输入时直接解析为0,不需要给每个输入框单独加编辑回调,适合项目中多处使用百分比输入框的场景:
import SwiftUI

// 空输入自动返回0的百分比格式化器
struct ZeroDefaultPercentFormat: ParseableFormatStyle {
    var parseStrategy: Strategy = .init()
    
    func format(_ value: Double) -> String {
        value.formatted(.percent)
    }
    
    struct Strategy: ParseStrategy {
        func parse(_ value: String) throws -> Double {
            let content = value.trimmingCharacters(in: .whitespacesAndNewlines)
            // 空内容、仅输入百分号时都返回0
            if content.isEmpty || content == "%" {
                return 0
            }
            // 正常数值走默认解析逻辑
            let numStr = content.replacingOccurrences(of: "%", with: "")
            guard let num = Double(numStr) else { return 0 }
            return num / 100
        }
    }
}

extension ParseableFormatStyle where Self == ZeroDefaultPercentFormat {
    static var zeroDefaultPercent: ZeroDefaultPercentFormat { .init() }
}

// 使用方式和系统内置格式完全一致
struct ContentView: View {
    @State var a = Double()
    @State var b = Double()

    var body: some View {
        VStack(spacing: 20) {
            HStack {
                Text("Number 1")
                TextField("Enter Number 1", value: $a, format: .zeroDefaultPercent)
            }
            HStack {
                Text("Number 2")
                TextField("Enter Number 2", value: $b, format: .zeroDefaultPercent)
            }
        }
        .padding()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:51:19