Swift中User Defaults无法在App启动时加载字符串数组问题
问题根源与解决方案
你的问题核心是数据存储和读取的类型不匹配:初始化cemeteryEmoji时期望读取一个[String]数组,但触发墓地事件时,你把数组拼接成字符串存进了UserDefaults。App重启后,初始化时无法把字符串转成数组,就会用默认的空数组;而viewDidLoad里直接读取UserDefaults的字符串显示,所以看起来控件加载了正确内容,但后续操作时用的是空数组,导致重新计数。
具体修正步骤:
修正初始化逻辑:
改用计算属性自动处理UserDefaults的读写,避免类型不匹配和手动同步出错:var cemeteryEmoji: [String] { get { UserDefaults.standard.stringArray(forKey: "CemeteryEmoji") ?? [] } set { UserDefaults.standard.set(newValue, forKey: "CemeteryEmoji") } }修正墓地事件的存储逻辑:
不要把数组拼接成字符串存储,直接保存数组。修改addCemeteryEmoji函数:func addCemeteryEmoji() { var currentEmojis = cemeteryEmoji currentEmojis.append("🪦") cemeteryEmoji = currentEmojis // 通过计算属性自动保存到UserDefaults playerOneCemeteries.text = currentEmojis.joined() }修正viewDidLoad的显示逻辑:
直接用本地的cemeteryEmoji数组更新UI,不用重复读取UserDefaults:override func viewDidLoad() { super.viewDidLoad() playerOneCemeteries.text = cemeteryEmoji.joined() print(cemeteryEmoji) }额外优化点:
- 读取牛的数量时,直接用
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
相关产品推荐
相关产品推荐

