Reputation: 1015
I'm having some problems when trying to save/archive an object using NSCoding. I essentially have a class QA which defines a question and answer, I also have a class Volume which contains several attributes including an array of QA objects.
The error occurs when the NSKeyedArchiver.archiveRootObject method is called. My suspicion is that it is to do with the array of QA objects because if I comment out that part the exception isn't thrown.
My Volume class inherits from NSObject and NSCoding and the QA object inherits from NSObject only.
The exception thrown is: ...encodeWithCoder:]: unrecognized selector sent to instance 0x600000077c80
The method being used to archive is:
static func save() {
print("starting save...")
let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
let ArchiveURL = DocumentsDirectory.appendingPathComponent("volumesData")
NSKeyedArchiver.archiveRootObject(VolumeTableViewController.volumesArray, toFile: ArchiveURL.path)
print("Ending save...")
}
My Volume class is:
import Foundation
class Volume: NSObject, NSCoding {
let volumeNumber: Int
var completed: Bool
var questionsData: [QA]
init (volumeNumber: Int, completed: Bool, questionsData: [QA]) {
self.volumeNumber = volumeNumber
self.completed = completed
self.questionsData = questionsData
}
// MARK: NSCoding
public convenience required init?(coder aDecoder: NSCoder) {
let volumeNumber = aDecoder.decodeObject(forKey: "volumeNumber") as! Int
let completed = aDecoder.decodeObject(forKey: "completed") as! Bool
let questionsData = aDecoder.decodeObject(forKey: "questionsData") as! [QA]
self.init(volumeNumber: volumeNumber, completed: completed, questionsData: questionsData)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(volumeNumber, forKey: "volumeNumber")
aCoder.encode(completed, forKey: "completed")
aCoder.encode(questionsData, forKey: "questionsData")
}
}
And my QA class is:
import Foundation
class QA: NSObject {
let questionsText: String
let answerText: [String]
let correctAnswer: [Bool]
var selectedAnswer: [Bool?]
// Create standard initiator
init(questionsText:String, answerText: [String], correctAnswer: [Bool], selectedAnswer: [Bool?]) {
self.questionsText = questionsText
self.answerText = answerText
self.correctAnswer = correctAnswer
self.selectedAnswer = selectedAnswer
}
}
Any thoughts?
Upvotes: 0
Views: 381
Reputation: 5190
QA should also adopt NSCoding.All the custom properties of an object should be archivable as per rule every object in your object's object graph also conforms to NSCoding.
Use Codable protocol for Swift 4.
Upvotes: 2