升级Xcode 9.3后NSNumber转Float出现异常问题
关于Xcode 9.3中NSNumber转Float用
as?失败的问题解析 我之前也踩过这个坑!这其实是Swift 4.1(对应Xcode 9.3版本)对NSNumber与原生数值类型的as?转换逻辑做了严格调整导致的。
问题原因拆解
当你用NSNumber(value: 1.12)初始化时,这个NSNumber内部存储的是Double类型的数值。而1.12这个值是无法被Float精确表示的——Float的精度只有6-7位有效数字,1.12用二进制浮点数存储会存在微小的精度损失。
Swift 4.1之后,as?类型转换会严格执行无损检查:如果NSNumber存储的数值无法被目标类型(这里是Float)精确还原,转换就会失败返回nil。而1.00是可以被Float精确表示的,所以m as? Float能顺利成功。
至于Float(truncating: n),它属于截断式初始化逻辑,不会检查精度匹配度,直接将NSNumber的数值近似转换为Float,所以无论是否能精确表示都会执行成功。
解决方案
根据你的业务需求,可以选以下几种处理方式:
- 如果必须保证转换是完全无损精确的,继续使用
as? Float,但要做好nil的兜底处理; - 如果允许近似值(大部分业务场景都适用),可以用下面几种更可靠的转换方式:
let n = NSNumber(value: 1.12) // 方式1:使用truncating初始化器 let z = Float(truncating: n) // 方式2:直接调用NSNumber的floatValue属性 let z2 = n.floatValue // 方式3:先转成Double再转Float(效果和floatValue一致) let z3 = Float(n.doubleValue)
这个变化是Swift团队为提升类型安全性做出的调整,避免开发者无意中引入精度损失的问题,只是刚升级版本的时候容易踩这个小坑~
内容的提问来源于stack exchange,提问作者Sander48k
相关产品推荐
相关产品推荐

