So I have an app for a Midwestern car game where you count cows when you're driving and when you see a cemetery you lose half your cows. Whenever someone sees a cemetery, I have an emoji appear as an appended array of string, so they keep adding up. My problem is I can save the array to user defaults and it will print it correctly, but whenever I relaunch the app, the array goes back to a blank array of strings. So I know the data is saved correctly, just not loading when the app launches.
class ViewController: UIViewController {
@IBOutlet weak var playerOneNameText: UITextField!
@IBOutlet weak var numberOfCowsPlayerOne: UILabel!
@IBOutlet weak var playerOneCows: UILabel!
@IBOutlet weak var playerOneCemeteries: UILabel!
let userDefaults = UserDefaults.standard
var cemeteryEmoji: [String] = UserDefaults.standard.object(forKey: "CemeteryEmoji")! as? [String] ?? []
It will also strangely load the correct array in the field for display, but will start over any time a new cemetery is added:
override func viewDidLoad() {
super.viewDidLoad()
if userDefaults.value(forKey: "CemeteryEmoji") != nil{
playerOneCemeteries.text = "\(UserDefaults.standard.object(forKey: "CemeteryEmoji")!)"
print(cemeteryEmoji)
}else {
playerOneCemeteries.text = ""
}
}
And here's the function for all the cemetery data:
@IBAction func playerOneCemetery(_ sender: UIButton) {
let cemeteryCows = UserDefaults.standard.integer(forKey: "TotalCows") / 2
self.userDefaults.set(cemeteryCows, forKey: "TotalCows")
print(cemeteryCows)
self.numberOfCowsPlayerOne.text = "\(self.userDefaults.string(forKey: "TotalCows")!) cows"
addCemeteryEmoji()
print(UserDefaults.standard.object(forKey: "CemeteryEmoji")!)
func addCemeteryEmoji() {
cemeteryEmoji.append("🪦")
print(cemeteryEmoji)
self.playerOneCemeteries.text = "\(cemeteryEmoji.joined())"
userDefaults.set(cemeteryEmoji.joined(), forKey: "CemeteryEmoji")
}
}
So I'm not sure if it's an issue simply when the app loads or if I need to save it a different way (although as I said, that works perfectly fine with all the print statements). Any help would be great.
The error occurs because you join
the array right before saving it which creates a single string.
And when you relaunch the app object(forKey: "CemeteryEmoji")! as? [String]
fails.
I highly recommend to name the array more meaningful and use the dedicated API array(forKey:)
.
Name the array in plural form and declare an empty array
var cemeteryEmojis = [String]()
In viewDidLoad
load the array from UserDefaults
override func viewDidLoad() {
super.viewDidLoad()
if let emojis = userDefaults.array(forKey: "CemeteryEmoji") as? [String] {
playerOneCemeteries.text = "\(emojis.joined())"
cemeteryEmojis = emojis
print(cemeteryEmojis)
} else {
playerOneCemeteries.text = ""
}
}
And delete joined()
in the set
line of addCemeteryEmoji
func addCemeteryEmoji() {
cemeteryEmojis.append("🪦")
print(cemeteryEmojis)
self.playerOneCemeteries.text = "\(cemeteryEmojis.joined())"
userDefaults.set(cemeteryEmojis, forKey: "CemeteryEmoji")
}