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

Swift中User Defaults无法在App启动时加载字符串数组问题

问题根源与解决方案

你的问题核心是数据存储和读取的类型不匹配:初始化cemeteryEmoji时期望读取一个[String]数组,但触发墓地事件时,你把数组拼接成字符串存进了UserDefaults。App重启后,初始化时无法把字符串转成数组,就会用默认的空数组;而viewDidLoad里直接读取UserDefaults的字符串显示,所以看起来控件加载了正确内容,但后续操作时用的是空数组,导致重新计数。

具体修正步骤:

  1. 修正初始化逻辑:
    改用计算属性自动处理UserDefaults的读写,避免类型不匹配和手动同步出错:

    var cemeteryEmoji: [String] {
        get {
            UserDefaults.standard.stringArray(forKey: "CemeteryEmoji") ?? []
        }
        set {
            UserDefaults.standard.set(newValue, forKey: "CemeteryEmoji")
        }
    }
    
  2. 修正墓地事件的存储逻辑:
    不要把数组拼接成字符串存储,直接保存数组。修改addCemeteryEmoji函数:

    func addCemeteryEmoji() {
        var currentEmojis = cemeteryEmoji
        currentEmojis.append("🪦")
        cemeteryEmoji = currentEmojis // 通过计算属性自动保存到UserDefaults
        playerOneCemeteries.text = currentEmojis.joined()
    }
    
  3. 修正viewDidLoad的显示逻辑:
    直接用本地的cemeteryEmoji数组更新UI,不用重复读取UserDefaults:

    override func viewDidLoad() {
        super.viewDidLoad()
        playerOneCemeteries.text = cemeteryEmoji.joined()
        print(cemeteryEmoji)
    }
    
  4. 额外优化点:

    • 读取牛的数量时,直接用integer(forKey:),避免字符串转换的潜在错误:
      let cemeteryCows = UserDefaults.standard.integer(forKey: "TotalCows") / 2
      userDefaults.set(cemeteryCows, forKey: "TotalCows")
      numberOfCowsPlayerOne.text = "\(cemeteryCows) cows"
      
    • 给UserDefaults的key定义常量,避免拼写错误:
      private enum UserDefaultsKey {
          static let cemeteryEmoji = "CemeteryEmoji"
          static let totalCows = "TotalCows"
      }
      

完整修正后的关键代码片段:

class ViewController: UIViewController {
    
    @IBOutlet weak var playerOneNameText: UITextField!
    @IBOutlet weak var numberOfCowsPlayerOne: UILabel!
    @IBOutlet weak var playerOneCows: UILabel!
    @IBOutlet weak var playerOneCemeteries: UILabel!
  
    private enum UserDefaultsKey {
        static let cemeteryEmoji = "CemeteryEmoji"
        static let totalCows = "TotalCows"
    }
    
    // 用计算属性自动处理UserDefaults的读写
    var cemeteryEmoji: [String] {
        get {
            UserDefaults.standard.stringArray(forKey: UserDefaultsKey.cemeteryEmoji) ?? []
        }
        set {
            UserDefaults.standard.set(newValue, forKey: UserDefaultsKey.cemeteryEmoji)
            // 可选:手动同步,确保数据立即写入磁盘
            UserDefaults.standard.synchronize()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始化UI显示
        playerOneCemeteries.text = cemeteryEmoji.joined()
        let currentCows = UserDefaults.standard.integer(forKey: UserDefaultsKey.totalCows)
        numberOfCowsPlayerOne.text = "\(currentCows) cows"
    }
    
    @IBAction func playerOneCemetery(_ sender: UIButton) {
        let currentCows = UserDefaults.standard.integer(forKey: UserDefaultsKey.totalCows)
        let cemeteryCows = currentCows / 2
        UserDefaults.standard.set(cemeteryCows, forKey: UserDefaultsKey.totalCows)
        numberOfCowsPlayerOne.text = "\(cemeteryCows) cows"
        
        addCemeteryEmoji()
        print(cemeteryEmoji)
    }
    
    func addCemeteryEmoji() {
        var updatedEmojis = cemeteryEmoji
        updatedEmojis.append("🪦")
        cemeteryEmoji = updatedEmojis
        playerOneCemeteries.text = updatedEmojis.joined()
    }
}

这样修改后,数据的存储和读取类型保持一致,App重启后cemeteryEmoji会正确加载之前保存的数组,后续添加表情也会基于已有数组继续累加。

内容的提问来源于stack exchange,提问作者BenG94

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:05:17