【问题标题】:NSCoding required initializer in inherited classes in SwiftNSCoding 在 Swift 的继承类中需要初始化器
【发布时间】:2015-10-30 22:03:17
【问题描述】:

我有符合 NSObjectNSCoding 的类 Foo 我希望能够坚持使用 NSKeyedArchiver 我想创建类 Bar,它是 Foo 的子类,它也将符合 NSObject 和 @ 987654325@。我在理解如何在子类中创建 required convenience init?(coder aDecoder: NSCoder) 时遇到问题。

所以类Foo...

class Foo: NSObject, NSCoding {
  let identifier:String
  init(identifier:String) {
    self.identifier = identifier
  }

  override var description:String {
    return "Foo: \(identifier)"
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(identifier, forKey: "identifier")
  }

  required convenience init?(coder aDecoder: NSCoder) {
    guard let identifier = aDecoder.decodeObjectForKey("identifier") as? String
      else {
        return nil
    }
    self.init(identifier:identifier)
  }
}

然后类 Bar ...

class Bar:Foo {
  let tag:String

  init(identifier:String, tag:String) {
    self.tag = tag
    super.init(identifier: identifier)
  }

  override var description:String {
    return "Bar: \(identifier) is \(tag)"
  }
}

我可以通过添加以下方法来编译它以使其符合 NSCoding 兼容

  override func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(tag, forKey: "tag")
    super.encodeWithCoder(aCoder)
  }

这是有道理的,因为我调用super.encodeWithCoder(...) 重用超级使这个干燥。我遇到的问题是创建required convenience init?(...) 我似乎可以编译它的唯一方法是这样做......

  required convenience init?(coder aDecoder:NSCoder) {
    guard let identifier = aDecoder.decodeObjectForKey("identifier") as? String,
          let tag        = aDecoder.decodeObjectForKey("tag") as? String
      else {
        return nil
    }

    self.init(identifier:identifier, tag:tag)
  }

我基本上已经复制了超类所需的初始化程序,然后为子类属性添加了额外的解码方法。这种方法似乎不正确...

有没有更好的方法来实现这个?

【问题讨论】:

  • super.init(coder: aDecoder)

标签: ios swift cocoa-touch


【解决方案1】:

在所需的 init 方法中解码并分配所有子类属性后,立即调用:

super.init(coder: aDecoder)

【讨论】:

  • 不完全确定您要将呼叫添加到super.init(coder:aDecoder) 的位置,请提供更多详细信息.. 谢谢
【解决方案2】:

已经考虑了一段时间,并相信这是实现这一点的正确方法。

原因在于 Swift 强制对象初始化的方式。便利初始化器只能在self 上调用所需的初始化器。只有所需的初始化程序才能在super 上调用init

因此,初始化子类对象的唯一方法是在调用子类所需初始化程序之前解码所有必需的初始化参数...然后调用超类初始化程序

这是您可以复制到游乐场https://gist.github.com/vorlando/dc29ba98c93eaadbc7b1的代码

【讨论】:

  • 您好,请给我的答案打分的人提供解释...谢谢
【解决方案3】:

我在 Playground 中尝试过您的代码,当我勾选错误的红色圆圈时,它只是自动添加代码。

编码就像你的函数需要方便初始化。

示例代码:

required convenience init?(coder aDecoder: NSCoder)
{
    fatalError("init(coder:) has not been implemented")
}

【讨论】:

  • 这解决了为编译程序而需要初始化程序的问题。仍然需要实现便利初始化程序,否则当您尝试解码存档对象时,您将生成fatalErrorNSKeyedUnarchiver.unarchiveObjectWithFile(_:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多