在@AppStorage中无法将String转换为Int的技术求助
解决@AppStorage字符串转数值类型并实现乘法运算的问题
核心解决方案
直接将@AppStorage的存储类型改为数值类型(推荐用Double支持小数薪水,若只需整数可换Int),同时给TextField做字符串与数值的双向绑定转换,最后通过计算属性实时实现乘法运算。
修改后的完整代码
import SwiftUI struct HomeView: View { var body: some View { NavigationView { ExtractedView() } } } struct ExtractedView: View { @State var monthString = Date().getMonthString().lowercased().capitalized // 用Double存储输入数值,替代原String类型 @State private var salaryPh: Double = 0.0 @State private var hoursPm: Double = 0.0 // 直接将@AppStorage定义为Double类型,默认值设为0.0 @AppStorage("SALARY_KEY") var savedSalary: Double = 0.0 @AppStorage("HOURS_KEY") var savedHoursPm: Double = 0.0 // 计算属性:实时计算月薪并格式化 var monthlySalary: String { let total = salaryPh * hoursPm return String(format: "%.2f", total) } var body: some View { ZStack { BackgroundView() CalendarView() RoundedRectangle(cornerRadius: 40) .frame(width: 225, height: 100) .foregroundColor(.blue) .offset(y: 190) VStack(alignment: .center, spacing: 13) { Text("Your netto-salary per hour") .foregroundColor(Color.white) .font(Font.system(size: 23, design: .rounded)) .fontWeight(.light) // 自定义绑定,实现Double与String双向转换 TextField("Salary", text: Binding( get: { String(format: "%.2f", salaryPh) }, set: { if let value = Double($0) { salaryPh = value } } )) .frame(width: 100, height: 50) .background(.black) .opacity(0.5) .foregroundColor(Color.white) .multilineTextAlignment(.center) .font(.system(.body, design: .monospaced)) .overlay ( RoundedRectangle(cornerRadius: 15) .stroke(Color.blue, lineWidth: 4) ) .onChange(of: salaryPh) { newValue in savedSalary = newValue } .onAppear { salaryPh = savedSalary } } .offset(y: -150) VStack(alignment: .center, spacing: 13) { Text("Hours in this month") .foregroundColor(Color.white) .font(Font.system(size: 23, design: .rounded)) .fontWeight(.light) // 同样的自定义绑定处理小时数 TextField("Hours", text: Binding( get: { String(format: "%.2f", hoursPm) }, set: { if let value = Double($0) { hoursPm = value } } )) .foregroundColor(Color.white) .frame(width: 100, height: 50) .background(.black) .opacity(0.5) .multilineTextAlignment(.center) .font(.system(.body, design: .monospaced)) .overlay ( RoundedRectangle(cornerRadius: 15) .stroke(Color.blue, lineWidth: 4) ) .onChange(of: hoursPm) { newValue in savedHoursPm = newValue } .onAppear { hoursPm = savedHoursPm } } .offset(y: -20) VStack(spacing: 20) { Text("In \(monthString) i make:") .foregroundColor(Color.white) .font(Font.system(size: 23, design: .rounded)) .fontWeight(.light) // 显示计算后的月薪 Text(monthlySalary) .foregroundColor(.white) .font(.system(size: 30, design: .monospaced)) .fontWeight(.bold) } .offset(y: 165) } } } struct HomeView_Previews: PreviewProvider { static var previews: some View { HomeView() } } // 补充原项目缺失的扩展和视图,避免编译错误 extension Date { func getMonthString() -> String { let formatter = DateFormatter() formatter.dateFormat = "MMMM" return formatter.string(from: self) } } struct BackgroundView: View { var body: some View { Color.black.ignoresSafeArea() } } struct CalendarView: View { var body: some View { EmptyView() // 替换为你的实际日历视图 } }
关键修改说明
- @AppStorage类型优化:直接将存储变量定义为
Double,@AppStorage原生支持数值类型存储,无需通过字符串中转,避免转换错误。 - TextField双向绑定:通过自定义
Binding实现数值与字符串的转换,既保证输入框显示友好的字符串格式,又能将输入值转为数值类型处理。 - 实时计算逻辑:新增计算属性
monthlySalary,用salaryPh * hoursPm实时计算月薪,并格式化显示为带2位小数的字符串。 - 数据同步:通过
onChange监听数值变化,自动同步到@AppStorage;onAppear时从@AppStorage加载保存的数值到本地状态。
如果只需要整数运算,只需把所有Double替换为Int,并将格式化字符串改为"%d"即可。
内容的提问来源于stack exchange,提问作者Deniss
相关产品推荐
相关产品推荐

