我认为你有点过于复杂了。您可以使用它Measurement
来为您完成大部分工作。如果您想以不同的方式编辑测量值,只需拥有单一的事实来源。下面是一个例子height
import SwiftUI
//The key for something like this is to save everything to one variable in this case I will use centimeters as the source of truth
struct Height{
///Source of truth
var centimeters: Double = 0
///This will have a multitude of uses and has its on Formatter for when you want to display units based on locale, etc
var heightInCentimeters: Measurement<UnitLength> {
get{
Measurement(value: centimeters, unit: .centimeters)
}
//A measurement of any UnitLength kind will be converted to cm
//Make sure you use the given units and you dont create new ones or you will get zero
set{
centimeters = newValue.converted(to: .centimeters).value
}
}
/// centimeters converted to feet using Swift.Measurement
var feet: Double {
get{
return heightInCentimeters.converted(to: .feet).value
}
set{
heightInCentimeters = Measurement(value: newValue, unit: UnitLength.feet)
}
}
/// centimeters converted to feet and inches. They depend on each other like this
var feetAndInches: (feet:Int, inches:Int){
get{
let feetDouble = heightInCentimeters.converted(to: .feet).value
//figure out the decimal
let feetForInches = feetDouble.truncatingRemainder(dividingBy: 1)
//remove the decimal
let feet = feetDouble - feetForInches
//convert decimal to inches
let inches = Measurement(value: feetForInches, unit: UnitLength.feet).converted(to: .inches).value
//return whole numbers
return (Int(feet), Int(inches))
}
set(newValue){
let ftCM = Measurement(value: Double(newValue.feet), unit: UnitLength.feet).converted(to: .centimeters).value
let inCM = Measurement(value: Double(newValue.inches), unit: UnitLength.inches).converted(to: .centimeters).value
centimeters = ftCM + inCM
}
}
}
struct UserData {
var age: Int = 18
var height: Height
}
class UserDataViewModel: ObservableObject {
@Published var userData: UserData = UserData(height: Height())
}
struct UserDataView: View {
@StateObject var vm: UserDataViewModel = UserDataViewModel()
var numFormatter: NumberFormatter{
let format = NumberFormatter()
format.maximumFractionDigits = 2
return format
}
var body: some View {
//Notice that TextField with formatter only "saves" the new value when the user presses return/done on the keyboard
List{
Section(header: Text("age"), content: {
HStack{
Text("age")
TextField("age", value: $vm.userData.age, formatter: numFormatter)
}
})
Section(header: Text("height = \(vm.userData.height.heightInCentimeters.description)"), content: {
HStack{
Text("feet")
TextField("feet", value: $vm.userData.height.feet, formatter: numFormatter)
}
VStack{
HStack{
Text("feet")
TextField("feet", value: $vm.userData.height.feetAndInches.feet, formatter: numFormatter)
}
HStack{
Text("inches")
TextField("inches", value: $vm.userData.height.feetAndInches.inches, formatter: numFormatter)
}
}
HStack{
Text("centimeters")
TextField("centimeters", value: $vm.userData.height.centimeters, formatter: numFormatter)
}
})
}
}
}
struct UserDataView_Previews: PreviewProvider {
static var previews: some View {
UserDataView()
}
}
这段代码可以是任意长度。不仅仅是身高。