Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift NSCoding Not working

Tags:

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];  } 
like image 215
chris Avatar asked Jun 16 '14 07:06

chris


2 Answers

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()     } 
like image 146
Jared Messenger Avatar answered Sep 23 '22 15:09

Jared Messenger


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

  1. File system :

    NSKeyedArchiver.archiveRootObject(student, toFile: "Here give your file path") 
  2. NSUserDefaults :

    let data = NSKeyedArchiver.archivedDataWithRootObject(student) NSUserDefaults.standardUserDefaults().setObject(data, forKey: "student") 

Unarchiving

  1. File system :

    NSKeyedUnarchiver.unarchiveObjectWithFile(student, toFile: "Here give your file path") 
  2. 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") } 
like image 22
Adarsh G J Avatar answered Sep 21 '22 15:09

Adarsh G J