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

SwiftUI中@State变量Decimal?默认值查询及CurrencyField空值显示问题

问题分析与解决

核心问题1:变量名不匹配

你的代码存在明显的变量关联错误——CurrencyField绑定的是mortgageAmount,但文本修饰器判断的却是amount,两个变量完全独立,导致输入值时amount根本不会变化。先修正这个基础问题,统一变量名:

@State var amount: Decimal?

ZStack(alignment: .leading){
    CurrencyField("",value: Binding(get: {
        amount.map { NSDecimalNumber(decimal: $0) }
    }, set: { number in amount = number?.decimalValue}))

    // 后续文本逻辑保持使用amount
}

核心问题2:错误的空值判断逻辑

你用String(describing: amount).isEmpty判断空值,但Swift中String(describing: nil)返回的是字符串"nil",而非空字符串,这就是未输入值时判断始终不成立的原因。

正确的判断方式是直接检查可选值状态,或结合业务需求判断是否为0:

// 仅判断是否为nil
let isAmountEmpty = amount == nil
// 若业务上0也视为空值
let isAmountEmpty = amount == nil || amount == 0

查看@State var amount: Decimal?的默认值

Swift中所有可选类型的默认值都是nil,Decimal?也不例外。如果要验证这一点,可在视图加载时打印或用调试工具查看:

.onAppear {
    print("amount默认值:\(amount)") // 输出结果为"amount默认值:nil"
}

也可以直接用Xcode断点调试,在运行时查看变量面板中amount的取值。

重构"Balance"文本的修饰器

重复的条件判断会让代码冗余,可通过以下两种方式简化:

方式1:用计算属性封装判断逻辑

@State var amount: Decimal?

private var isAmountEmpty: Bool {
    amount == nil || amount == 0
}

var body: some View {
    ZStack(alignment: .leading){
        CurrencyField("",value: Binding(get: {
            amount.map { NSDecimalNumber(decimal: $0) }
        }, set: { number in amount = number?.decimalValue}))

        Text("Balance")
            .foregroundColor(isAmountEmpty ? Color(Design.TextDark!) : Color(Design.accent!))
            .font(Font.custom(Design.PrimaryFont, size: 16))
            .offset(y: isAmountEmpty ? 0 : -25)
            .scaleEffect(isAmountEmpty ? 1 : 0.8, anchor: .leading)
    }
}

方式2:自定义ViewModifier封装样式

@State var amount: Decimal?

var body: some View {
    ZStack(alignment: .leading){
        CurrencyField("",value: Binding(get: {
            amount.map { NSDecimalNumber(decimal: $0) }
        }, set: { number in amount = number?.decimalValue}))

        Text("Balance")
            .font(Font.custom(Design.PrimaryFont, size: 16))
            .applyPlaceholderStyle(isFilled: !(amount == nil || amount == 0))
    }
}

// 自定义修饰器
struct PlaceholderStyle: ViewModifier {
    let isFilled: Bool
    func body(content: Content) -> some View {
        content
            .foregroundColor(isFilled ? Color(Design.accent!) : Color(Design.TextDark!))
            .offset(y: isFilled ? -25 : 0)
            .scaleEffect(isFilled ? 0.8 : 1, anchor: .leading)
    }
}

extension View {
    func applyPlaceholderStyle(isFilled: Bool) -> some View {
        modifier(PlaceholderStyle(isFilled: isFilled))
    }
}

内容的提问来源于stack exchange,提问作者k.thomas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:46:06