swiftdictionarynskeyedunarchiver

NSKeyedUnarchiver.unarchivedObject returning nil for dictionary


I am trying to update my code to iOS12. Below is my code:

class CurrentGameState: NSObject, NSSecureCoding {

static var supportsSecureCoding: Bool = true
var currentTest1 = Int()
var currentUnitPositionColumn = [String: Int]()
static var currentGameStatus = CurrentGameState(unit: "init", test: 1, column: -1)
var currentTest1 = Int()
var currentUnitPositionColumn = [String: Int]()

init(unit: String, test: Int, column: Int) {

    currentTest1 = test
    currentUnitPositionColumn[unit] = column
}
func encode(with aCoder: NSCoder) {

    aCoder.encode(currentTest1, forKey: test1)
    aCoder.encode(currentUnitPositionColumn, forKey: currentColumn)
}

required init(coder aDecoder: NSCoder) {

    self.currentTest1 = aDecoder.decodeInteger(forKey: test1)
    self.currentUnitPositionColumn = aDecoder.decodeObject(forKey: currentColumn) as! [String : Int]
}

extension PersistData {
func newSaveMatchInfo(saveType: GlobalConstants.saveType) {

    let gameDataFile = "GameData" + String(describing: saveType)
    if let url = getFileURLInAppDocumentDirectory(fileName: gameDataFile) {

        do{

            let archive = try NSKeyedArchiver.archivedData(withRootObject: CurrentGameState.currentGameStatus, requiringSecureCoding: true)
            try archive.write(to: url)

        }catch{
            print("!!!!!Error saving Game data == \(error)")
        }
    }
}

func newLoadMatchInfo(saveType: GlobalConstants.saveType) {

    let gameDataFile = "GameData" + String(describing: saveType)

    guard let gameData = try? Data(contentsOf: getFileURLInAppDocumentDirectory(fileName: gameDataFile)!),
        let gameInfo = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [CurrentGameState.self], from: gameData as Data ) else {

            print("!!!!!Error gameInfo = try? NSKeyedUnarchiver.unarchivedObject failed ")
            return
    }

    CurrentGameState.currentGameStatus = gameInfo as! 
}
}

When I run this code, the NSKeyedUnarchiver works for the Int currentTest1, but returns nil when it hits the dictionary currentUnitPositionColumn. The old code shown below for the NSKeyedUnarchiver works fine, but unarchiveObject(withFile: is deprecated in iOS12.

func loadMatchInfo(saveType: GlobalConstants.saveType) {
    let gameDataFile = "GameData" + String(describing: saveType)
    if let url = getFileURLInAppDocumentDirectory(fileName: gameDataFile) {
        if let gameData = NSKeyedUnarchiver.unarchiveObject(withFile: url.path) as? CurrentGameState {
            CurrentGameState.currentGameStatus = gameData
        }
    }
}

There is something about the Dictionary that will not work with my new code. Any help would be greatly appreciated.


Solution

  • Your code works fine if you replace:

    let gameInfo = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [CurrentGameState.self], from: gameData as Data ) else {
    

    with:

    let gameInfo = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(gameData) else {
    

    I suspect it fails using unarchivedObject(ofClasses: because you can't list Dictionary<String, Int>.