使用UserDefaults保存第二个UIColor时遇解包nil错误,求解决方案
兄弟,你碰到的这个崩溃,核心原因是强制解包了UserDefaults里不存在的键值——第一次加第二个颜色的保存逻辑时,UserDefaults里还没有对应的键(比如你可能用了"TheSecondUIColour"这类新键),value(forKey:)会返回nil,你直接用as! String强制解包,自然就触发了Unexpectedly found nil的致命错误。
之前第一个颜色能正常跑,大概率是因为你提前给"TheMainUIColour"设过默认值,或者用户已经设置过这个颜色,所以UserDefaults里有值兜底。
下面给你几个靠谱的解决办法,按稳妥程度排序:
1. 用可选绑定+默认值替代强制解包(最推荐)
这是最安全的写法,既处理了nil的情况,又能给默认颜色兜底:
// 读取第二个UIColor的示例代码 let defaultSecondHex = "#FFFFFF" // 这里换成你想要的默认十六进制颜色 let secondColorHex = UserDefaults.standard.string(forKey: "TheSecondUIColour") ?? defaultSecondHex let secondColor = UIColor(hex: secondColorHex)
这里用string(forKey:)替代value(forKey:),它直接返回可选字符串,再用??空合运算符,当值为nil时就用预设的默认Hex,完全避免强制解包的风险。
2. 提前给UserDefaults设置初始默认值
在App启动时(比如AppDelegate的didFinishLaunchingWithOptions或者SceneDelegate的scene(_:willConnectTo:options:)里),给所有颜色键初始化默认值,这样后续读取时就不会出现nil:
// 初始化颜色默认值的函数 func setupDefaultColorSettings() { let defaults = UserDefaults.standard // 先检查是否已经设置过,避免每次启动覆盖用户的自定义设置 if defaults.string(forKey: "TheMainUIColour") == nil { defaults.set("#000000", forKey: "TheMainUIColour") } if defaults.string(forKey: "TheSecondUIColour") == nil { defaults.set("#FFFFFF", forKey: "TheSecondUIColour") } }
调用这个函数后,后续读取时就算用原来的写法也不会崩溃,但还是建议搭配可选绑定,双重保险。
3. 给UIColor扩展安全的Hex初始化方法
你现在用的UIColor(hex:)可能没处理无效Hex的情况,扩展一个带默认值的初始化方法,进一步降低崩溃风险:
extension UIColor { convenience init(hex: String, defaultColor: UIColor = .black) { // 先处理Hex字符串的格式问题 var cleanHex = hex.trimmingCharacters(in: .whitespacesAndNewlines) cleanHex = cleanHex.replacingOccurrences(of: "#", with: "") var rgbValue: UInt64 = 0 // 如果解析失败,直接返回默认颜色 guard Scanner(string: cleanHex).scanHexInt64(&rgbValue) else { self.init(cgColor: defaultColor.cgColor) return } let red = CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0 let green = CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0 let blue = CGFloat(rgbValue & 0x0000FF) / 255.0 self.init(red: red, green: green, blue: blue, alpha: 1.0) } }
这样就算Hex字符串无效,也会返回你设置的默认颜色,不会崩溃。
最后再啰嗦一句:永远尽量避免用as!强制解包可选类型,除非你100%确定这个值一定存在,否则用if let/guard let的可选绑定,或者??空合运算符来处理nil情况才是稳妥的做法。
内容的提问来源于stack exchange,提问作者The Mamba

