Swift中UnitMass通过symbol与静态初始化格式化结果不一致问题
Swift中UnitMass通过symbol初始化导致格式化异常的解决方案
问题现象
使用UnitMass的静态属性(如UnitMass.kilograms)创建Measurement时,格式化输出正常;但通过UnitMass(symbol:)初始化单位后创建的Measurement,格式化结果完全错误(例如42.0千克会显示为“0 μg”)。调试时实例看似有效,但格式化逻辑失效。
由于UnitMass不支持Codable,无法直接存入SwiftData,只能存储单位的symbol,因此必须解决通过symbol还原标准单位的问题。
重现代码:
import UIKit let mass = UnitMass.kilograms let anotherMass = UnitMass(symbol: mass.symbol) let measurement = Measurement(value: 42.0, unit: mass) let anotherMeasurement = Measurement(value: 42.0, unit: anotherMass) let formatted = measurement.formatted() // 输出 "42 kg" let anotherFormatted = anotherMeasurement.formatted() // 输出 "0 μg"(异常)
原因分析
UnitMass(symbol:)方法创建的是自定义质量单位,而非系统预定义的标准单位:
- 系统预定义的
UnitMass.kilograms等静态属性,内部已配置好与单位体系匹配的转换系数(converter),格式化时能正确识别单位并计算数值。 - 自定义单位的默认转换规则是基于单位体系基准单位(此处为微克)的恒等转换,导致系统无法识别其与“千克”的实际换算关系,最终格式化时出现数值异常。
解决方案
放弃使用UnitMass(symbol:)初始化单位,改为维护一个symbol到预定义UnitMass实例的映射表,通过存储的symbol查表还原标准单位:
1. 创建单位映射扩展
extension UnitMass { // 维护symbol与预定义单位的映射,按需添加所需单位 static let symbolToUnit: [String: UnitMass] = [ UnitMass.kilograms.symbol: .kilograms, UnitMass.grams.symbol: .grams, UnitMass.milligrams.symbol: .milligrams, UnitMass.micrograms.symbol: .micrograms, UnitMass.metricTons.symbol: .metricTons, UnitMass.pounds.symbol: .pounds, UnitMass.ounces.symbol: .ounces ] }
2. 从SwiftData还原单位与Measurement
// 示例:从SwiftData中取出保存的数值和symbol let savedValue: Double = 42.0 let savedSymbol: String = "kg" // 通过映射表获取标准单位,创建正常的Measurement if let restoredUnit = UnitMass.symbolToUnit[savedSymbol] { let restoredMeasurement = Measurement(value: savedValue, unit: restoredUnit) let formatted = restoredMeasurement.formatted() // 正常输出 "42 kg" }
说明
- 映射表可根据业务需求扩展,添加所有需要支持的质量单位。
- 存储时只需保存预定义单位的
symbol,还原时通过映射表匹配,确保使用的是系统标准单位,避免自定义单位的转换逻辑错误。
内容的提问来源于stack exchange,提问作者JonEasy
相关产品推荐
相关产品推荐

