Подтвердить что ты не робот

Swift NSCoding Не работает

У меня возникают проблемы с использованием NSCoding в Swift. Я попытался выполнить протокол, но получаю сбой при вызове метода save(). Xcode выводит меня на строку в encodeWithCoder. Здесь мой код, любые предложения будут идти по пути.

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


    }
}

Я написал save() и load() для вызова .

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];

}
4b9b3361

Ответ 1

Совсем немного изменилось с помощью Swift, так как этот вопрос был задан. Я не могу воспроизвести ошибку, которую вы видите, но я смог заставить NSCoding работать с Swift 1.0 с помощью кода ниже.

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
    }
}

Для загрузки сохраненного экземпляра или создания нового при необходимости

    // 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()
    }

Ответ 2

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")

    }
}

Вышеуказанная строка класса, целочисленная, кодировка массива реализована.

Предположим, что ученик является экземпляром класса Student

Архивация

  • Файловая система:

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

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

разархивирование

  • Файловая система:

    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:

Путь к файлу для сохранения/чтения

func saveFileLocation() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentDirectory = paths[0] as! String
    return documentDirectory.stringByAppendingPathComponent("savefile")
}

Ответ 3

Вот еще один пример с объектом с именем SNStock, который имеет два строковых свойства: ticker и 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
  }
}

Ответ 4

Следующий код не работает

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")
    }
}

Обязательно напишите вот так

class Hero : NSObject, NSCoding {

    var heroID: String?
    var title: String?
    var imageName: String?
    var detail: String?
    var star: String?

    override init() {

    }
}