Swift中UserDefaults将Any转为Bool/Int:如何区分1/0与布尔值?
解决UserDefaults中Bool与Int类型混淆的问题
问题的核心原因是UserDefaults底层基于Objective-C实现,Swift的Bool和Int都会被装箱成NSNumber存储。当用value(forKey:)取值时,Swift会优先将NSNumber桥接为Int,导致原本存储的Bool被识别成1或0,无法直接通过as Bool匹配。
解决方案:通过NSNumber的类型元数据区分原始类型
不要用value(forKey:),改用object(forKey:)获取原始对象,然后检查NSNumber的objCType属性——这个属性会保留值的原始类型信息,能准确区分是从Bool转来的NSNumber还是原生Int转来的。
示例代码:
let rawValue = UserDefaults.standard.object(forKey: key) switch rawValue { case let number as NSNumber: // 判断是否为原始Bool类型 if strcmp(number.objCType, @encode(Bool)) == 0 { return bool(number.boolValue) } // 判断是否为原始Int类型 else if strcmp(number.objCType, @encode(Int)) == 0 { return int(number.intValue) } // 可扩展处理其他数值类型(如Float、Double) case let value as Bool: // 兜底处理直接存储的Swift Bool(极少出现) return bool(value) case let value as Int: // 兜底处理直接存储的Swift Int(极少出现) return int(value) default: // 处理非数值类型或不存在的key break }
补充说明
- 存值时尽量使用UserDefaults的类型专属方法,比如
set(true, forKey: "isEnabled"),这样取值时用bool(forKey:)可以直接拿到正确的Bool值,从根源避免类型混淆。 - 如果是历史遗留的混合存储场景,上面的
objCType判断是最可靠的区分方式,不会把实际存储的Int 1误判为true,也不会把Bool true误判为Int 1。
内容的提问来源于stack exchange,提问作者Evgeniy Kleban
相关产品推荐
相关产品推荐

