SwiftUI如何实现根据用户地区自动切换度量单位的体重选择器?
SwiftUI体重选择器适配地区单位方案
问题描述
作为SwiftUI新手,我正在开发一款体重(及身高)选择器,需要根据用户的地区/语言环境自动适配单位:
- 公制地区显示体重选项:
40kg, 42.5kg, 45kg, …, 300kg - 英制地区显示体重选项:
80lb, 85lb, 90lb, …, 600lb
以下是我硬编码英制单位的示例代码:
import SwiftUI struct SetMyWeightView: View { // 目前仅适配英制,如何同时支持公制?公制需展示[40kg, 42.5kg, 45kg, .... 300kg],英制保持[80lb, 85lb, 90lb, ..., 600lb] @State private var myWeight: Int? var body: some View { Form { Section { Picker("", selection: $myWeight) { // 隐藏体重选项 Text("Hide").tag(nil as Int?) // 生成80到600、步长为5的英制体重列表 ForEach(Array(stride(from: 80, to: 601, by: 5)), id: \.self) { weight in Text("\(weight) lb").tag(weight as Int?) } } .pickerStyle(.wheel) } header: { Text("Weight") } } } } #Preview { SetMyWeightView() }

解决方案
1. 利用Locale自动判断单位系统
SwiftUI的环境变量Locale可以直接获取用户的地区设置,通过usesMetricSystem属性快速判断是否使用公制单位。我们可以通过@Environment(\.locale)注入当前环境的Locale实例。
2. 统一存储类型并动态生成选项
由于公制体重是带小数的数值(如42.5kg),英制是整数,我们需要把myWeight的类型改为Double?来兼容两种情况。然后根据Locale判断结果,动态生成对应的体重范围和步长。
3. 修改后的完整代码
import SwiftUI struct SetMyWeightView: View { // 改为Double?兼容公制小数和英制整数 @State private var myWeight: Double? // 注入当前环境的Locale @Environment(\.locale) private var locale var body: some View { Form { Section { Picker("", selection: $myWeight) { // 隐藏体重选项 Text("Hide").tag(nil as Double?) // 根据单位系统动态生成选项 ForEach(weightOptions, id: \.self) { weight in Text("\(formattedWeight(weight)) \(unitSuffix)") .tag(weight as Double?) } } .pickerStyle(.wheel) } header: { Text("Weight") } } } // 单位后缀:公制显示kg,英制显示lb private var unitSuffix: String { locale.usesMetricSystem ? "kg" : "lb" } // 生成对应的体重选项列表 private var weightOptions: [Double] { if locale.usesMetricSystem { // 公制:40到300,步长2.5 return Array(stride(from: 40, to: 301, by: 2.5)) } else { // 英制:80到600,步长5 return Array(stride(from: 80, to: 601, by: 5)).map(Double.init) } } // 格式化体重显示:公制保留1位小数(如42.5),英制显示整数(如85) private func formattedWeight(_ weight: Double) -> String { if locale.usesMetricSystem { return String(format: "%.1f", weight) } else { return String(format: "%.0f", weight) } } } // 添加不同Locale的预览,方便测试 #Preview("Metric") { SetMyWeightView() .environment(\.locale, Locale(identifier: "zh_CN")) } #Preview("Imperial") { SetMyWeightView() .environment(\.locale, Locale(identifier: "en_US")) }
关键说明
- Locale判断:通过
locale.usesMetricSystem自动识别用户地区的单位系统,无需手动判断国家代码。 - 动态选项生成:分别为公制和英制设置对应的起始值、结束值和步长,确保选项符合需求。
- 格式化显示:公制显示1位小数,英制显示整数,提升用户体验。
- 预览测试:添加不同Locale的预览,可直接在Xcode中切换查看两种单位的效果。
内容的提问来源于stack exchange,提问作者daydayup
相关产品推荐
相关产品推荐

