为什么我收到“类型'书签'不符合协议'可解码'”错误消息?
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
}
}
我不希望保存出版物var,因为出版物拥有书签,但书签需要知道它属于哪个出版物。 Publication的decode init将书签引用设置为自身。
答案 0 :(得分:29)
由于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)
}
}
答案 1 :(得分:20)
为什么我收到“类型'书签'不符合协议'可解码'”错误消息
这可能是因为出版物不是可解码的(你没有表明它是什么,所以很难说)或者因为weak
上的publication
指定。
无论哪种方式,都很容易修复:您只需要实现init(from:)
来完成Decodable的实现;编译器只是告诉你这个实现无法合成。
答案 2 :(得分:15)
事后看来,我在尝试将Codable
设置为由NSNumber类型变量组成的类时收到了类似的错误。见下图:
将NSNumber
更改为原始数据类型Int
解决了这个问题。见下文:
我猜这可能适用于需要桥接到Swift标准库值类型(如NSString,NSArray等)的其他数据类型
答案 3 :(得分:10)
您可能收到此消息的另一个原因是,如果您的CodingKeys枚举不完整。如果数据类型具有三个属性,则您的CodingKeys枚举也需要具有三个属性/名称大小写。
答案 4 :(得分:6)
答案 5 :(得分:1)
简而言之,在实现Codable时,所有非原始数据类型(均值类类型或可能是Objective-c类)的属性都必须是Codable。
weak var publication: Publication?
在这种情况下,发布属于类别类,因此发布必须已实现Codable
答案 6 :(得分:1)
有点愚蠢,但以防万一。之所以出现此错误,是因为我放了enum CodingKeys: CodingKeys
而不是enum CodingKeys: CodingKey
。
答案 7 :(得分:0)
我遇到了类似的问题,偶然发现了此修复程序。因为我是Swift的新手,所以我不确定它为什么起作用!如果有人知道,我将不胜感激。
我更改了此内容
let id, type: Int
对此:
let id: Int
let type: Int
答案 8 :(得分:0)
仅因为您的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方法,因为现在可以综合实现。
答案 9 :(得分:0)
只有在具有默认值的情况下,才可以从编码键枚举中省略属性。
如果在解码实例时不存在这些属性,或者如果某些属性不应包含在编码表示形式中,请从CodingKeys枚举中省略属性。从CodingKeys省略的属性需要一个默认值,以便其包含类型能够自动接收与Decodable或Codable相符的信息。
答案 10 :(得分:0)
我通过将结构名称更改为我想要的结构的当前swift文件来解决此问题。例如,我要将其放入BookmarkModel.swift
中,因此键入:
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
}
}
更改为此:
class BookmarkModel: 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
}
}
答案 11 :(得分:-1)
任何应编码的对象类都必须采用NSCoding协议并实现其方法。来自apple