如何将CoreData存储的UnitType字符串转为Swift Measurement可用的Unit类型?
解决字符串转Unit类型的问题
你之前的错误在于使用UnitLength(symbol:)初始化单位——这个方法接收的是单位的符号(比如"cm"),而不是你存储的"UnitLength.centimeters"这种类型成员的标识字符串,因此创建的单位实例无效,格式化时出现错误结果。
下面提供两种可行的解决方案:
方案一:字典映射(推荐,性能更优)
提前创建一个字符串到对应Unit实例的映射字典,直接通过存储的字符串查找对应的单位,这种方式高效且可控:
// 提前定义所有需要支持的单位映射 let unitMapping: [String: Unit] = [ "UnitLength.centimeters": UnitLength.centimeters, "UnitLength.inches": UnitLength.inches, "UnitLength.feet": UnitLength.feet, "UnitLength.meters": UnitLength.meters, "UnitMass.kilograms": UnitMass.kilograms, "UnitMass.pounds": UnitMass.pounds, // 根据业务需求添加更多单位 ] // 使用示例 let personHeight = 190.0 let personHeightUnit = "UnitLength.centimeters" if let unit = unitMapping[personHeightUnit] as? UnitLength { let height = Measurement(value: personHeight, unit: unit) let formattedText = height.formatted( .measurement(width: .abbreviated, usage: .personHeight) .locale(Locale(identifier: "en-US")) ) Text("Height = \(formattedText)") // 输出预期结果:Height = 6 ft, 2.8 in }
方案二:反射自动匹配
通过Swift的反射机制,解析字符串中的类型和成员名,自动获取对应的Unit实例,无需手动维护字典,适合单位类型较多且频繁新增的场景:
func convertToUnit(from unitString: String) -> Unit? { // 拆分字符串为类型名和单位成员名 let components = unitString.components(separatedBy: ".") guard components.count == 2 else { return nil } let typeName = components[0] let unitMemberName = components[1] // 匹配对应的Unit类型 guard let unitType: Any.Type = { switch typeName { case "UnitLength": return UnitLength.self case "UnitMass": return UnitMass.self case "UnitTemperature": return UnitTemperature.self // 添加其他需要支持的Unit类型 default: return nil } }() else { return nil } // 反射遍历静态属性,找到匹配的单位实例 let mirror = Mirror(reflecting: unitType) for child in mirror.children { if child.label == unitMemberName, let unit = child.value as? Unit { return unit } } return nil } // 使用示例 let personHeight = 190.0 let personHeightUnit = "UnitLength.centimeters" if let unit = convertToUnit(from: personHeightUnit) as? UnitLength { let height = Measurement(value: personHeight, unit: unit) let formattedText = height.formatted( .measurement(width: .abbreviated, usage: .personHeight) .locale(Locale(identifier: "en-US")) ) Text("Height = \(formattedText)") // 输出预期结果:Height = 6 ft, 2.8 in }
内容的提问来源于stack exchange,提问作者Peel
相关产品推荐
相关产品推荐

