0

I have the following data architecture, where Orchestra has many Sections, and each Section has many Players :

enter image description here

All 3 classes conform to NSCoding protocol and have the necessary methods implemented. According to this SO question, it should work since NSCoding works recursively.

Inside the Orchestra singleton class, I have the following methods for saving and retrieving Sections:

let sectionArchivalURL: URL = {

    let documentDirectories = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentDirectory = documentDirectories.first!

    return documentDirectory.appendingPathComponent("sections.archive") //gets archived Player objects
} ()

func saveChanges() -> Bool {
    print ("Saving sections to: \(sectionArchivalURL.path)")
    return NSKeyedArchiver.archiveRootObject(allSections, toFile: sectionArchivalURL.path)
}

Section also conforms to NSCoding:

//MARK: - NSCoding methods
func encode(with aCoder: NSCoder) {
    aCoder.encode(sectionName, forKey: "sectionName")
    aCoder.encode(allPlayers, forKey: "allPlayers")
}

required init(coder aDecoder: NSCoder) {

    sectionName = aDecoder.decodeObject(forKey: "sectionName") as! String
    allPlayers = aDecoder.decodeObject(forKey: "allPlayers") as! [Player]

    super.init()
}

Similarly, Player also conforms to NSCoding:

//MARK: - NSCoding methods
func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "playerName")        
    print ("encoding Player") //does not get called
}

required init(coder aDecoder: NSCoder) {

    name = aDecoder.decodeObject(forKey: "playerName") as! String
    super.init()
}

Saving is confirmed working. However, when the app relaunches, I am able to view my teams, but the containing Players are empty. I also know that the encoding function in Player did not get called. What am I doing incorrectly?

Community
  • 1
  • 1
daspianist
  • 5,336
  • 8
  • 50
  • 94
  • The error says that you have an array that matches the "allPlayers" key but you're trying to force it to be a single `Player` object. – Phillip Mills Apr 03 '17 at 19:48
  • @PhillipMills great insight - thanks. Fixing it did get rid of the error, but now no `Player`s show up. – daspianist Apr 03 '17 at 19:50

1 Answers1

0

Leave everything the same except your Player class. Here is the way I got it working:

    func encode(with aCoder: NSCoder) {
        let encName = NSKeyedArchiver.archivedData(withRootObject: name)
        aCoder.encode(encName, forKey: "playerName")        
        print ("encoding Player")
    }

    required init(coder aDecoder: NSCoder) {
        let tmpName = aDecoder.decodeObject(forKey: "playerName")
        name = NSKeyedUnarchiver.unarchiveObject(with: tmpName as! Data) as! String
    }