You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UserDefaults保存第二个UIColor时遇解包nil错误,求解决方案

解决保存第二个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:48:21