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?

2
  • 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. Commented Apr 3, 2017 at 19:48
  • @PhillipMills great insight - thanks. Fixing it did get rid of the error, but now no Players show up. Commented Apr 3, 2017 at 19:50

1 Answer 1

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
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.