Read and Write Plists Question

I am using a plists to save high scores in my game. So far I can read from a plist but I can't write to it, any ideas?. Here is my code so far, the getBestTime function seems to work, but the updateTime doesn't. The best times for each level are set to -1 by default. Thanks!


func getBestTime(levelNumber : Int) -> Int {
        var levels: NSArray?
        var bestTime : Int = -1
        if let path = Bundle.main.path(forResource: LEVEL_TIMES, ofType: "plist") {
            levels = NSArray(contentsOfFile: path)
            print(levels)
            if let levArr = levels {
                let level : NSDictionary = levArr[levelNumber - 1] as! NSDictionary
                bestTime = (level[HIGH_SCORE_KEY] as? Int)!
            }
        }
        return bestTime
    }
    
    func updateTime(levelNumber : Int, time : Int) -> Bool {
        var levels: NSMutableArray?
        if let path = Bundle.main.path(forResource: "LevelTimes", ofType: "plist") {
            levels = NSMutableArray(contentsOfFile: path)
            if let levArr = levels {
                let level : NSMutableDictionary = levArr[levelNumber - 1] as! NSMutableDictionary
                let curTime = (level[HIGH_SCORE_KEY] as? Int)!
                if curTime == -1 || curTime > time {
                    level.setValue(time, forKey: HIGH_SCORE_KEY)
                    levels?.write(toFile: path, atomically: true)
                    print(levels)
                    return true
                }
            }
        }

> I can read from a plist but I can't write to it


Assuming bundle main path means root level, that's why. You need to relocate the plist to a folder such as documents or library before it's writeable.


See: https://stackoverflow.com/questions/23867337/how-can-i-save-retrieve-delete-update-my-data-in-plist-file-in-ios

Unrelated to KMT's answer, a couple of "Don't Do That"s in your code:


— Don't use NSArray or NSMutableArray in modern Swift code (except in a few rare cases where it's unavoidable). The only good justification currently is if you need reference semantics rather than value semantics, but in that case you're better off wrapping a Swift array (value semantics) in a custom Swift class (reference semantics). Swift arrays can do everything you need, usually easier, and with less confusion about bridging and type casting to Obj-C.


— Don't use path strings, but get used to using URLs instead. Path strings are not deprecated (yet), but URLs are definitely preferred. In particular, if you see an API (like contentsOfFile:) that takes a string or does not return/throw an error, avoid that API completely. There's always a more modern replacement that returns or throws an error, and there's always an alternative that takes a URL.


(In a few cases, the replacement is in a different class, which is a bit confusing. In your case, the NSArray file I/O methods are replaced by methods on Data/NSData, and you're expected to create your own Data/NSData object from the array first.)


Incidentally for something like high scores (that is, not a lot of data), I'd suggest storing them in UserDefaults, not in a freestanding plist file. It's a lot easier to code.

Read and Write Plists Question
 
 
Q