Swift NSCoding Not working

前端 未结 4 1703
小蘑菇
小蘑菇 2020-12-23 21:53

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 p

相关标签:
4条回答
  • 2020-12-23 22:24

    Here is another example with an object called SNStock that has two string properties, ticker and name:

    import Foundation
    
    class SNStock: NSObject, NSCoding {
    
      let ticker: NSString
      let name: NSString
    
      init(ticker: NSString, name: NSString) {
        self.ticker = ticker
        self.name = name
      }
    
      // MARK: NSCoding
    
      required init(coder aDecoder: NSCoder) {
        self.ticker = aDecoder.decodeObjectForKey("ticker") as! NSString
        self.name = aDecoder.decodeObjectForKey("name") as! NSString
      }
    
      func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(ticker, forKey: "ticker")
        aCoder.encodeObject(name, forKey: "name")
      }
    
      // MARK: NSObjectProtocol
    
      override func isEqual(object: AnyObject?) -> Bool {
        if let object = object as? SNStock {
          return self.ticker == object.ticker &&
            self.name == object.name
        } else {
          return false
        }
      }
    
      override var hash: Int {
        return ticker.hashValue
      }
    }
    
    0 讨论(0)
  • 2020-12-23 22:25
    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")
    }
    
    0 讨论(0)
  • 2020-12-23 22:43

    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()
        }
    
    0 讨论(0)
  • 2020-12-23 22:43

    The following code does not work

    class Hero : AnyObject, NSCoding {
    
        var heroID: String?
        var title: String?
        var imageName: String?
        var detail: String?
        var star: String?
    
        init() {
    
        }
    
    
        func update(_ dictionary: Dictionary<String, AnyObject>) {
    
            heroID = dictionary["imageName"] as? String
            title = dictionary["title"] as? String
            imageName = dictionary["imageName"] as? String
            detail = dictionary["detail"] as? String
            star = dictionary["star"] as? String
    
        }
        required init?(coder aDecoder: NSCoder) {
            heroID = aDecoder.decodeObject(forKey: "heroID") as? String
            title = aDecoder.decodeObject(forKey: "title") as? String
            imageName = aDecoder.decodeObject(forKey: "imageName") as? String
            detail = aDecoder.decodeObject(forKey: "detail") as? String
            star = aDecoder.decodeObject(forKey: "star") as? String
        }
    
        func encode(with aCoder: NSCoder) {
            aCoder.encode(heroID, forKey: "heroID")
            aCoder.encode(title, forKey: "title")
            aCoder.encode(imageName, forKey: "imageName")
            aCoder.encode(detail, forKey: "detail")
            aCoder.encode(star, forKey: "star")
        }
    }
    

    Be sure to write like this

    class Hero : NSObject, NSCoding {
    
        var heroID: String?
        var title: String?
        var imageName: String?
        var detail: String?
        var star: String?
    
        override init() {
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题