arraysswiftswiftuinsuserdefaults

Swift/SwiftUI func not reading updated values from variables set in previous func


I am trying to have the getLastScore function to get the most recent score from an array and use it to update a view. I have confirmed that the addScore function is working as intended, but when I try to access the updated array, all I get is nil.

import Foundation

class QuizScoreManager: ObservableObject {
    
    struct QuizScore: Codable {
        let date: Date
        let score: Int
        let quizTitle: String
    }
    
    @Published var scores: [QuizScore] = []
    
    func addScore(score: Int, quizTitle: String) {
        let quizScore = QuizScore(date: Date(), score: score, quizTitle: quizTitle)
        scores.append(quizScore)
        saveScores()
        objectWillChange.send()
    }
    
    func getScores(forQuizTitle quizTitle: String) -> [QuizScore] {
        return scores.filter { $0.quizTitle == quizTitle }
    }
    
    private func saveScores() {
        let encoder = JSONEncoder()
        if let encoded = try? encoder.encode(scores) {
            UserDefaults.standard.set(encoded, forKey: "quizScores")
        }
    }
    
    func printScores() {
        loadScores()
        for score in scores {
            print("Quiz Title: \(score.quizTitle), Score: \(score.score), Date: \(score.date)")
        }
    }

    func getLastScore(forQuizTitle quizTitle: String) -> Int? {
        let lastScore = scores.filter { $0.quizTitle == quizTitle }.last?.score
        print("Sending a lastScore value of: \(String(describing: lastScore))")
        return lastScore
    }



    
    private func loadScores() {
        if let savedScores = UserDefaults.standard.object(forKey: "quizScores") as? Data {
            let decoder = JSONDecoder()
            if let loadedScores = try? decoder.decode([QuizScore].self, from: savedScores) {
                scores = loadedScores
            }
        }
    }
    
    init() {
        loadScores()
    }
}

Solution

  • Maybe you are not accessing the instance of QuizScoreManager that you think you are. If the owner of this class is a View then it needs to be creating it as a StateObject, for example:

        @StateObject private var theQuizScoreManager = QuizScoreManager()