【问题标题】:How to add parameters to existing model when objects already saved?已保存对象时如何向现有模型添加参数?
【发布时间】:2017-05-20 00:28:19
【问题描述】:

我有一个 Bill 类,其中包含一些使用 NSKeyedArchiver 保存在 plist 文件中到文档目录的账单实例。

class Bill: NSObject, NSCoding {

  required init?(coder aDecoder: NSCoder) {
    name = aDecoder.decodeObject(forKey: "Name") as! String
    moPayment = aDecoder.decodeDouble(forKey: "Payment")
    super.init()
  }

  override init() {
    super.init()
  }

  var name = "Bill Name"
  var moPayment = 0.0

  func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "Name")
    aCoder.encode(moPayment, forKey: "Payment")
  }
}

func saveBillItems(_ bills: [Bill]) {
  let data = NSMutableData()
  let archiver = NSKeyedArchiver(forWritingWith: data)
  archiver.encode(bills, forKey: "BillItems")
  archiver.finishEncoding()
  data.write(to: dataFilePath(), atomically: true)
}

func loadBillItems() {
    let path = dataFilePath()
    if let data = try? Data(contentsOf: path) {

        let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
        bills = unarchiver.decodeObject(forKey: "BillItems") as! [Bill]
        unarchiver.finishDecoding()
    }
}

所有这些都按预期工作,但现在我正在尝试添加一个额外的参数来记录paidStatus。

class Bill: NSObject, NSCoding {

  required init?(coder aDecoder: NSCoder) {
    ...
    status = aDecoder.decodeObject(forKey: "Status") as! PaidStatus
    super.init()
  }

  ...

  var status = PaidStatus.unpaid

  enum PaidStatus {
    case overdue
    case upcoming
    case unpaid
    case paid
  }

  ...

  func encode(with aCoder: NSCoder) {
    ...
    aCoder.encode(status, forKey: "Status")
  }
}

func saveBillItems(_ bills: [Bill]) {
  ...
}

func loadBillItems() {
  ...
}

当我现在尝试运行应用程序时,我收到一个错误:“Unexpectedly found nil...”

status = aDecoder.decodeObject(forKey: "Status") as! PaidStatus

由于试图加载没有此参数的现有账单对象。

有没有办法将此参数添加到我现有的对象中,而不必删除它们并从头开始重新创建它们?

【问题讨论】:

  • 不要使用强制向下转换;使用 nil 合并运算符可能的条件向下转换
  • 这样做会给我一个编译器错误,因为状态不能采用可选值。

标签: ios swift nskeyedarchiver


【解决方案1】:

由于您的对象可能没有值,因此您需要使用可选的向下转换,而不是强制向下转换。由于status 不是可选的,您可以使用 nil 合并运算符来提供默认值

status = aDecoder.decodeObject(forKey: "Status") as? PaidStatus ?? .unpaid

【讨论】:

  • 这似乎有效,但是我收到了一个无法识别的选择器发送到实例 encodeWithCoder。我相信这可能与编码枚举和一个单独的问题有关。
猜你喜欢
  • 2018-01-27
  • 2019-10-28
  • 2023-02-15
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
相关资源
最近更新 更多