Swift4.1中Any转Float总是失败,是新特性还是Bug?
解决Swift 4.1中从[String: Any]字典获取Float值失败的问题
我之前也踩过这个坑!在旧版本Swift(比如对应Xcode9.2的Swift4.0)里,我们可以直接通过let float = dict["somekey"] as? Float从[String: Any]字典中获取Float值,但到了Swift4.1(对应Xcode9.3及以上版本),这个写法突然失效了——核心原因是字典中的字面量数值会被隐式推断为Double类型,而Double转Float的as?类型强转是不会成功的(因为二者是不同的类型,没有直接的桥接关系)。
我后来专门用Xcode9.2做了对比测试,代码如下:
// Xcode9.2(Swift4.0)环境测试结果:正常获取Float值 let dict1: [String: Any] = ["somekey": 3.14] if let floatVal = dict1["somekey"] as? Float { print("获取到Float值:\(floatVal)") // 输出:获取到Float值:3.14 } else { print("转Float失败") } // Xcode9.3(Swift4.1)环境测试结果:实际是Double类型 let dict2: [String: Any] = ["somekey": 3.14] if let floatVal = dict2["somekey"] as? Float { print("获取到Float值:\(floatVal)") // 不会执行此分支 } else if let doubleVal = dict2["somekey"] as? Double { print("实际是Double值:\(doubleVal)") // 输出:实际是Double值:3.14 }
针对这个问题,我整理了几种可行的解决方案:
- 方案一:先转Double再转Float
这是最直接的兼容写法,先把字典中的值转成Double,再手动转换成Float:
let dict: [String: Any] = ["somekey": 3.14] if let doubleVal = dict["somekey"] as? Double { let floatVal = Float(doubleVal) print("转换后的Float值:\(floatVal)") // 输出:转换后的Float值:3.14 }
- 方案二:构建字典时明确指定Float类型
如果字典是你自己构建的,可以在赋值时就明确标注类型,避免被隐式推断为Double:
let dict: [String: Any] = ["somekey": Float(3.14)] if let floatVal = dict["somekey"] as? Float { print("获取到Float值:\(floatVal)") // 正常输出 }
- 方案三:扩展字典添加便捷转换方法
如果需要频繁处理这种场景,可以给[String: Any]写一个扩展,统一处理各种数值类型转Float的情况:
extension Dictionary where Key == String, Value == Any { func floatValue(forKey key: String) -> Float? { switch self[key] { case let float as Float: return float case let double as Double: return Float(double) case let int as Int: return Float(int) case let int64 as Int64: return Float(int64) default: return nil } } } // 使用示例 let dict: [String: Any] = ["floatKey": 3.14, "intKey": 10, "doubleKey": 5.67] if let floatVal = dict.floatValue(forKey: "floatKey") { print(floatVal) // 3.14 } if let intToFloat = dict.floatValue(forKey: "intKey") { print(intToFloat) // 10.0 }
内容的提问来源于stack exchange,提问作者LYM
相关产品推荐
相关产品推荐

