Codable class 不符合 Decodable 协议
Codable class does not conform to protocol Decodable
为什么我会收到 "Type 'Bookmark' does not conform to protocol '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
}
}
我不想保存出版物变量,因为出版物拥有书签,但书签需要知道它属于哪个出版物。 Publication 的解码初始化会将书签引用设置为自身。
Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message
这要么是因为 Publication 不是 Decodable(您没有显示它是什么,所以很难说),要么是因为 publication
上的 weak
指定。
无论哪种方式,修复起来都很容易:你只需要实现init(from:)
即可完成Decodable的实现;编译器只是告诉你这个实现无法合成。
由于weak
引用,编译器无法合成所需的init(from:)
方法,需要自己编写。
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)
}
}
事后看来,我在尝试将 Codable
设置为由 NSNumber 类型变量组成的 class 时收到了类似的错误。见下图:
将 NSNumber
更改为原始数据类型 Int
解决了该问题。见下文:
我猜这对于需要桥接到 Swift 标准库值类型(例如 NSString、NSArray 等)的其他数据类型可能是正确的
我有一个类似的问题,我偶然发现了这个修复程序。由于我是 Swift 的新手,我不确定它为什么有效!如果有人知道,我将不胜感激。
我改变了这个:
let id, type: Int
对此:
let id: Int
let type: Int
您可能收到此消息的另一个原因是您的 CodingKeys 枚举不详尽。如果您的数据类型具有三个属性,那么您的 CodingKeys 枚举也需要具有三个 property/name 案例。
简而言之,在实现 Codable 时,所有非原始数据类型(意思是 class 类型或者可能是 objective-c class )的属性都必须是 Codable。
weak var publication: Publication?
在这种情况下,发布的类型为 class,因此发布必须已实现 Codable
仅仅因为您的 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
}
}
您不再需要 init 方法,因为现在可以合成实现。
您可以从编码键枚举中省略 属性,前提是它具有默认值。
Omit properties from the CodingKeys enumeration if they won't be present when decoding instances, or if certain properties shouldn't be included in an encoded representation. A property omitted from CodingKeys needs a default value in order for its containing type to receive automatic conformance to Decodable or Codable.
有点愚蠢,但以防万一它对其他人有帮助。我得到这个错误是因为我把 enum CodingKeys: CodingKeys
而不是 enum CodingKeys: CodingKey
.
要成为可编码的任何 class 必须全部 属性 可编码。
String、Int、Double 等标准库类型和 Date、Data 和 UR 等基础类型确认可编码协议,但有些不确认。
例如下面
注意 class 具有确认可编码协议的字符串的所有属性,因此没有错误:
但是 UIImage 不确认可编码协议,因此它抛出错误:
在类似的情况下,我遇到了同样的问题,因为我的 CodingKeys 中的变量名称与 class 变量不同。见下文
为什么我会收到 "Type 'Bookmark' does not conform to protocol '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
}
}
我不想保存出版物变量,因为出版物拥有书签,但书签需要知道它属于哪个出版物。 Publication 的解码初始化会将书签引用设置为自身。
Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message
这要么是因为 Publication 不是 Decodable(您没有显示它是什么,所以很难说),要么是因为 publication
上的 weak
指定。
无论哪种方式,修复起来都很容易:你只需要实现init(from:)
即可完成Decodable的实现;编译器只是告诉你这个实现无法合成。
由于weak
引用,编译器无法合成所需的init(from:)
方法,需要自己编写。
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)
}
}
事后看来,我在尝试将 Codable
设置为由 NSNumber 类型变量组成的 class 时收到了类似的错误。见下图:
将 NSNumber
更改为原始数据类型 Int
解决了该问题。见下文:
我猜这对于需要桥接到 Swift 标准库值类型(例如 NSString、NSArray 等)的其他数据类型可能是正确的
我有一个类似的问题,我偶然发现了这个修复程序。由于我是 Swift 的新手,我不确定它为什么有效!如果有人知道,我将不胜感激。
我改变了这个:
let id, type: Int
对此:
let id: Int
let type: Int
您可能收到此消息的另一个原因是您的 CodingKeys 枚举不详尽。如果您的数据类型具有三个属性,那么您的 CodingKeys 枚举也需要具有三个 property/name 案例。
简而言之,在实现 Codable 时,所有非原始数据类型(意思是 class 类型或者可能是 objective-c class )的属性都必须是 Codable。
weak var publication: Publication?
在这种情况下,发布的类型为 class,因此发布必须已实现 Codable
仅仅因为您的 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
}
}
您不再需要 init 方法,因为现在可以合成实现。
您可以从编码键枚举中省略 属性,前提是它具有默认值。
Omit properties from the CodingKeys enumeration if they won't be present when decoding instances, or if certain properties shouldn't be included in an encoded representation. A property omitted from CodingKeys needs a default value in order for its containing type to receive automatic conformance to Decodable or Codable.
有点愚蠢,但以防万一它对其他人有帮助。我得到这个错误是因为我把 enum CodingKeys: CodingKeys
而不是 enum CodingKeys: CodingKey
.
要成为可编码的任何 class 必须全部 属性 可编码。 String、Int、Double 等标准库类型和 Date、Data 和 UR 等基础类型确认可编码协议,但有些不确认。
例如下面
注意 class 具有确认可编码协议的字符串的所有属性,因此没有错误:
但是 UIImage 不确认可编码协议,因此它抛出错误:
在类似的情况下,我遇到了同样的问题,因为我的 CodingKeys 中的变量名称与 class 变量不同。见下文