I'm having trouble using NSCoding
in Swift. I have attempted to implement the protocol but I get a crash whenever I call my save()
method. Xcode pulls me up on the line in encodeWithCoder
. Here's my code, any suggestions would go along way.
class CourseList: NSObject, NSCoding { ... init(coder aDecoder: NSCoder!){ super.init() if aDecoder != nil { self.courses = aDecoder.decodeObjectForKey("courses") as Dictionary<String,course> } } func encodeWithCoder(aCoder: NSCoder!) { aCoder!.encodeObject(self.courses, forKey: "courses") // EXC_BAD_INSTRUCTOIN } }
I wrote save()
and load()
to call in a ViewController
.
func save() { var archivedObject = NSKeyedArchiver.archivedDataWithRootObject(History) //NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; var defaults = NSUserDefaults.standardUserDefaults() //[defaults setObject:archivedObject forKey:<key_for_archived_object>]; defaults.setObject(History.courses, forKey: "courses") defaults.synchronize() } func load() { var defaults = NSUserDefaults.standardUserDefaults() // NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; var archivedObject = defaults.objectForKey("courses") as NSData // NSData *archivedObject = [defaults objectForKey:<key_for_archived_object>]; History = NSKeyedUnarchiver.unarchiveObjectWithData(archivedObject) as Dictionary<String,course> //<your_class> *obj = (<your_class> *)[NSKeyedUnarchiver unarchiveObjectWithData:archivedObject]; }
Quite a bit has changed with Swift since this question was asked. I can't reproduce the error you're seeing, but I was able to get NSCoding to work with Swift 1.0 with the code below.
class CourseList: NSObject, NSCoding { var myCourses: Dictionary<String, String>? override init() {} required init(coder aDecoder: NSCoder) { self.myCourses = aDecoder.decodeObjectForKey("myCourses") as? Dictionary } func encodeWithCoder(aCoder: NSCoder) { if let courses = self.myCourses{ aCoder.encodeObject(courses, forKey: "myCourses") } } func populateCourses() { self.myCourses = ["cs101": "Hello World"] } func save() { let data = NSKeyedArchiver.archivedDataWithRootObject(self) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "courseList") } func clear() { NSUserDefaults.standardUserDefaults().removeObjectForKey("courseList") } class func loadSaved() -> CourseList? { if let data = NSUserDefaults.standardUserDefaults().objectForKey("courseList") as? NSData { return NSKeyedUnarchiver.unarchiveObjectWithData(data) as? CourseList } return nil } }
To load a saved instance or create a new one if needed
// Try loading a saved version first if let courseLs = CourseList.loadSaved() { println("loaded Save CourseList") } else { // Create a new Course List let courseLs: CourseList = CourseList() courseLs.populateCourses() courseLs.save() }
class Student: NSObject, NSCoding { var name: String! var className: String! var rollNo: Int! var marks: [Float]! // MARK: NSCoding required convenience init(coder decoder: NSCoder) { self.init() self.name = decoder.decodeObjectForKey("name") as String? self.className = decoder.decodeObjectForKey("className") as String? self.rollNo = decoder.decodeIntegerForKey("rollNo") self.marks = decoder.decodeObjectForKey("marks") as [Float]! } func encodeWithCoder(coder: NSCoder) { coder.encodeObject(self.name, forKey: "name") coder.encodeObject(self.className, forKey: "className") coder.encodeInt(Int32(self.rollNo), forKey: "rollNo") coder.encodeObject(self.marks, forKey: "marks") } }
Above class string,integer,array encoding are implemented.
suppose student is an instance of class Student
Archiving
File system :
NSKeyedArchiver.archiveRootObject(student, toFile: "Here give your file path")
NSUserDefaults :
let data = NSKeyedArchiver.archivedDataWithRootObject(student) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "student")
Unarchiving
File system :
NSKeyedUnarchiver.unarchiveObjectWithFile(student, toFile: "Here give your file path")
NSUserDefaults :
if let data = NSUserDefaults.standardUserDefaults().objectForKey("student") as? NSData { let student = NSKeyedUnarchiver.unarchiveObjectWithData(data) }
Addit:
File path for saving / reading
func saveFileLocation() -> String { let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) let documentDirectory = paths[0] as! String return documentDirectory.stringByAppendingPathComponent("savefile") }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With