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
相关产品推荐
相关产品推荐

