此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结
说在前面
上一篇我们什么都不考虑,垮垮垮写出了一个长度单位转换的小组件,但是细看用到了switch,写了很多感觉很复杂的代码,今天我们看下要怎么完善它,用上 Swift 自带的一些方法。
单位转换小组件(优化版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import SwiftUI
struct ContentView: View { @State private var input = 100.0 @State private var inputUnit = UnitLength.meters @State private var outputUnit = UnitLength.kilometers @FocusState private var inputIsFocused :Bool let units: [UnitLength] = [.feet, .meters, .kilometers, .miles, .yards] let formatter: MeasurementFormatter var result: String { let inputMeasurement = Measurement(value: input, unit: inputUnit) let outputMeasurement = inputMeasurement.converted(to: outputUnit) return formatter.string(from: outputMeasurement) } var body: some View { NavigationStack{ Form{ Section("输入你要转换的值"){ TextField("输入值",value: $input,format:.number) .keyboardType(.decimalPad) .focused($inputIsFocused) } Picker("选择你的单位",selection: $inputUnit){ ForEach(units,id:\.self){ Text(formatter.string(from: $0).capitalized) } } Picker("选择你想转换的单位",selection: $outputUnit){ ForEach(units,id:\.self){ Text(formatter.string(from: $0).capitalized) } } Section("结果"){ Text(result) } } } .navigationTitle("转换器") .toolbar{ if inputIsFocused{ Button("完成"){ inputIsFocused = false } } } } init(){ formatter = MeasurementFormatter() formatter.unitOptions = .providedUnit formatter.unitStyle = .long } }
|
实现效果图
可以看出 Picker 选择器下面的单位变成了英文,这是因为这里用到的是 swift 自带的一些方法,底层也支持这些单位的互相转换,汉字的话目前还没有直接可以实现的方法。
知识点
以下是这段新代码与之前代码的一些区别和新增的知识点:
区别:
- 使用了 UnitLength 类型来表示单位,而不是字符串。
- 使用 Measurement 和 MeasurementFormatter 类来进行单位转换和格式化,提供了更准确和规范的处理方式。
新增知识点:
- @FocusState :用于管理视图元素的焦点状态。
- toolbar:用于在视图顶部添加工具栏,并根据焦点状态显示 “完成” 按钮。
- 初始化方法 init :用于初始化 MeasurementFormatter 并设置其属性。
- 对单位的处理更加规范化和类型安全,利用了系统提供的相关类型和类来进行转换和展示。
MeasurementFormatter 是 Swift 中用于格式化 Measurement 对象的类。
Measurement 对象通常包含一个数值和一个单位。MeasurementFormatter 可以将这样的对象格式化为易于理解和阅读的字符串表示形式。
以下是 MeasurementFormatter 的一些重要属性和方法:
属性:
unitOptions :控制要显示的单位选项,例如 .providedUnit (使用提供的单位)、 .naturalScale (使用自然缩放的单位)等。
unitStyle :决定单位的显示风格,比如 .long (完整的单位名称,如 “米”)、 .short (缩写,如 “m”)、 .abbreviated (更简短的缩写)等。
方法:
string(from:) :这是主要的方法,用于将给定的 Measurement 对象转换为格式化的字符串。
使用 MeasurementFormatter 可以使单位的格式化更加灵活和准确,适应不同的需求和场景,确保单位的显示符合应用的要求和用户的期望。
进阶挑战
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| import SwiftUI
struct ContentView: View { @State private var input = 100.0 @State private var inputUnit: Dimension = UnitLength.meters @State private var outputUnit: Dimension = UnitLength.kilometers @State private var selectedUnits = 0 @FocusState private var inputIsFocused :Bool let conversions = ["距离","质量","温度","时间"] let unitTypes = [ [UnitLength.feet, UnitLength.meters, UnitLength.kilometers, UnitLength.miles, UnitLength.yards], [UnitMass.grams, UnitMass.kilograms, UnitMass.ounces, UnitMass.pounds], [UnitTemperature.celsius, UnitTemperature.fahrenheit, UnitTemperature.kelvin], [UnitDuration.hours, UnitDuration.minutes, UnitDuration.seconds] ] let formatter: MeasurementFormatter var result: String { let inputMeasurement = Measurement(value: input, unit: inputUnit) let outputMeasurement = inputMeasurement.converted(to: outputUnit) return formatter.string(from: outputMeasurement) } var body: some View { NavigationStack{ Form{ Section("输入你要转换的值"){ TextField("输入值",value: $input,format:.number) .keyboardType(.decimalPad) .focused($inputIsFocused) } Picker("转换类型",selection: $selectedUnits){ ForEach(0..<conversions.count, id:\.self){ Text(conversions[$0]) } } Picker("选择你的单位",selection: $inputUnit){ ForEach(unitTypes[selectedUnits],id:\.self){ Text(formatter.string(from: $0).capitalized) } } Picker("选择你想转换的单位",selection: $outputUnit){ ForEach(unitTypes[selectedUnits],id:\.self){ Text(formatter.string(from: $0).capitalized) } } Section("结果"){ Text(result) } } .navigationTitle("转换器") .toolbar { if inputIsFocused{ Button("完成"){ inputIsFocused = false } } } } } init(){ formatter = MeasurementFormatter() formatter.unitOptions = .providedUnit formatter.unitStyle = .long } }
|
实现效果图
可以看到我们实现了多种单位的转化。
说在后面
找bug:
- 发现之前 .navigationTitle 和 .toolbar 的方法位置错误了,造成效果一直没出来。
- 示例里还有一个给 .toolbar 下继续添加 .onChange 的方法,但是无奈报错,后续看看具体原因。