You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:50:30