Codable类不符合协议Decodable

Mel*_*ius 40 swift swift4 codable decodable

为什么我得到"类型'书签'不符合协议'可解码'"错误消息?

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}
Run Code Online (Sandbox Code Playgroud)

我不希望保存出版物var,因为出版物拥有书签,但书签需要知道它属于哪个出版物.Publication的解码初始化将书签引用设置为自身.

Dáv*_*tor 38

init(from:)由于weak引用,编译器无法合成所需的方法,因此您需要自己编写它.

class Bookmark: Codable {
    weak var publication: Publication?
    var indexPath: [Int]
    var locationInText = 0

    private enum CodingKeys: String, CodingKey {
        case indexPath
        case locationInText
    }

    init(publication: Publication?, indexPath: [Int]) {
        self.publication = publication
        self.indexPath = indexPath
    }

    required init(from decoder:Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        indexPath = try values.decode([Int].self, forKey: .indexPath)
        locationInText = try values.decode(Int.self, forKey: .locationInText)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我发现David的答案更有帮助,因为它有示例代码. (6认同)
  • 你的答案也是正确的,但马特是第一个。我不知道在这里应该做什么,但如果需要的话请启发我。谢谢。 (2认同)

mat*_*att 25

为什么我得到"类型'书签'不符合协议'可解码'"错误消息

这要么是因为出版物不是可解码的(你没有展示它是什么,所以很难说)或者因为它的weak名称publication.

无论哪种方式,它init(from:)都很容易修复:您只需要实现完成Decodable的实现; 编译器只是告诉你这个实现无法合成.


iOS*_*Ser 19

事后看来,我在尝试设置Codable由NSNumber类型变量组成的类时收到了类似的错误.见下图:

在此输入图像描述

更改NSNumber为原始数据类型Int解决了该问题.见下文:

在此输入图像描述

我猜这可能适用于需要桥接到Swift标准库值类型的其他数据类型,例如NSString,NSArray等等

  • 谢谢!就我而言,我试图使用 NSNumber。根据您的建议切换到 Int 并成功 (2认同)

小智 16

您可以获得此消息的另一个原因是您的CodingKeys枚举不是详尽无遗的.如果数据类型中有三个属性,那么您的CodingKeys枚举也需要有三个属性/名称大小写.

  • 还要检查CodingKeys中的拼写错误.如果只有一个不同的字符,代码将不会编译.(这是我的情况,谢谢@mikepj) (5认同)
  • 但指定您自己的“CodingKeys”的全部意义肯定是因为您想要排除一个或多个属性进行编码? (3认同)
  • 您**不需要在 CodingKeys** 中详尽地列出您的属性。如果您未列出某个属性,则需要为其提供默认值。 (3认同)

bik*_*ota 14

任何可编码的类都必须具有可编码的所有属性。标准库类型(如 String、Int、Double)和基础类型(如 Date、Data 和 UR)确认了可编码协议,但有些则不然。

例如,下面的 Note 类具有确认可编码协议的字符串的所有属性,因此不会出现错误: 字符串具有可编码协议,因此类没有错误

但 UIImage 不确认可编码协议,因此会抛出错误: Uiimage 没有可编码,它显示错误


Wis*_*ssa 7

仅仅是因为您的CodingKeys枚举并不详尽,所以publication可以在枚举中添加属性来实现这一点。

尝试这个:

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   // All your properties should be included
   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
      case publication   // this one was missing
   }
}
Run Code Online (Sandbox Code Playgroud)

您不再需要使用init方法,因为现在可以综合实现。


小智 7

在类似的情况下,我遇到了同样的问题,因为我的CodingKeys 中的变量名与类变量不同。见下文

在此处输入图片说明

  • 很容易犯这个错误,谢谢。我几乎走上了自定义初始化路线,然后看到了你的答案 (3认同)

Sai*_*aif 6

仅当属性具有默认值时,您才可以从编码键枚举中省略该属性。

来自苹果文档

如果解码实例时不存在 CodingKeys 枚举中的属性,或者某些属性不应包含在编码表示中,请忽略这些属性。CodingKeys 中省略的属性需要一个默认值,以便其包含类型自动符合 Decodable 或 Codable。