NSKeyedArchiver.archivedData 在 Swift 3 iOS 中不起作用

rez*_*afi 5 encode dealloc nskeyedarchiver ios swift

当尝试在 iOS swift 中对我的自定义对象进行编码时,从 Xcode 8.3 获取此错误

无法识别的选择器发送到实例 0x60800166fe80 *** -[NSKeyedArchiver dealloc]:警告:NSKeyedArchiver 在没有调用 -finishEncoding 的情况下被释放。

我的代码是这样的:

导入 UIKit 导入基础

class Place: NSObject {

    func setCustomObject(CustomObject obj:Any,Key key:String) {

        let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj)
        UserDefaults.standard.set(encodedObject, forKey: key)

    }
}
Run Code Online (Sandbox Code Playgroud)

Jur*_*oga 4

下面是一个如何使对象符合NSCoding. 基本上你需要提供两种方法的实现 -required convenience init?(coder decoder: NSCoder)encode(with aCoder: NSCoder)

class Book: NSObject, NSCoding {
  var title: String?
  var pageCount: Int?

  // Memberwise initializer
  init(title: String,pageCount: Int) {
   self.title = title
   self.pageCount = pageCount
  }

  // MARK: NSCoding


  // Here you will try to initialize an object from archve using keys you did set in `encode` method.
  required convenience init?(coder decoder: NSCoder) {
    guard let title = decoder.decodeObject(forKey: "title") as? String else { return nil }

    self.init(title: title, pageCount: decoder.decodeInteger(forKey: "pageCount"))
  }

  // Here you need to set properties to specific keys in archive
  func encode(with aCoder: NSCoder) {
    aCoder.encode(self.title, forKey: "title")
    aCoder.encodeCInt(Int32(self.pageCount), forKey: "pageCount")
  }
}
Run Code Online (Sandbox Code Playgroud)

我还建议将您的setCustomObject方法更改为:

func setCustomObject(obj:NSCoding, key:String) {
  let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj)
  UserDefaults.standard.set(encodedObject, forKey: key)
}
Run Code Online (Sandbox Code Playgroud)

这样编译器可以防止您传递NSKeyedArchiver不符合NSCoding协议的对象。

如果您不想在init方法中提供所有属性,可以使用默认值:

init(title : String? = nil, pageCount: Int? = nil){
  self.title = title
  self.pageCount = pageCount
}
Run Code Online (Sandbox Code Playgroud)

现在您可以只初始化对象而无需任何属性。像那样Book()