问题是List类型不符合Codable,下面的类不能插入Realm。
例如,
class Book: Codable {
var name: String = ""
var author: String = ""
var tags = [String]()
}
考虑上面的类符合Codable,如果将此类存储到Realm,则需要使用List<Object>
类型而不是[String]
class Book: Object, Codable {
@objc dynamic var name: String = ""
@objc dynamic var author: String = ""
var tags = List<Tag>()
required convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
author = try container.decode(String.self, forKey: .author)
tags = try container.decode(List<Tag>.self, forKey: .tags) // this is problem.
}
}
class Tag: Object, Codable {
@objc dynamic var string: String = ""
required convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
string = try container.decode(String.self, forKey: .string)
}
}
要符合Codable,应该实现Decodable
协议。 (required convenience init(from decoder: Decoder) throws
)
但是,List
类型不符合Codable
(Decodable
),如果类具有List
类型,则无法使用Codable。
如何解决此问题?
谢谢,
答案 0 :(得分:9)
我们可以使用扩展名使List符合Codable:
extension List : Decodable where Element : Decodable {
public convenience init(from decoder: Decoder) throws {
self.init()
var container = try decoder.unkeyedContainer()
while !container.isAtEnd {
let element = try container.decode(Element.self)
self.append(element)
}
} }
extension List : Encodable where Element : Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
for element in self {
try element.encode(to: container.superEncoder())
}
} }
如果其他人需要,我还为RealmOptional提供了扩展。
https://gist.github.com/ansonyao/41137bb3cbbca8ef31a13b6bc96ee422
答案 1 :(得分:5)
你快到了。在初始化程序内,您可以使用解码的数组初始化列表。基本上,改变
tags = try container.decode(List<Tag>.self, forKey: .tags) // this is problem.
到
let tagsArray = try container.decode([Tag].self, forKey: .tags)
tags = List(tagsArray) // Now you are good
正如评论中所指出的,List
构造函数不再像这样工作
你现在想要:
tags.append(objectsIn: tagsArray)
答案 2 :(得分:4)
接受的答案只有一个问题。 Realm指定列表应为 try:
data = s.recv(buf_len)
if data is not None and len(data) > 0:
while True:
new_data = s.recv(buf_len)
if new_data is None or len(new_data) == 0:
break
data = data + new_data
except socket.timeout:
if data is not None and self.callback is not None:
logger.debug(f"Received packet: {data}")
incoming = data.decode('utf-8')
print incoming
# Process Data
(常量)因此,要修改解决方案以遵循最佳实践,您只需将列表设为let
,然后循环将结果附加到数组中。
let
// Change this Line in [Your Code]
// to a let (Constant)
至var tags = List<Tag>()
然后改变
let tags = List<Tag>()
到
tags = try container.decode(List<Tag>.self, forKey: .tags)
答案 3 :(得分:2)
这就是您创建Realm / Swift 4 Codable模型的方法。
有关JSON响应的详细信息,模型和&amp; URLSession:Read this article
import RealmSwift
class VendorsList : Object, Decodable {
@objc dynamic var id : Int = 0
@objc dynamic var name : String?
@objc dynamic var logo : String?
// Create your Realm List.
var kitchensList = List<VendorKitchens>()
override class func primaryKey() -> String? {
return "id"
}
private enum CodingKeys: String, CodingKey {
case id
case name
case logo
// Set JSON Object Key
case kitchensList = "kitchens"
}
public required convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.logo = try container.decode(String.self, forKey: .logo)
// Map your JSON Array response
let kitchens = try container.decodeIfPresent([VendorKitchens].self, forKey: .kitchensList) ?? [VendorKitchens()]
kitchensList.append(objectsIn: kitchens)
}
}
class VendorKitchens : Object, Decodable {
@objc dynamic var id : Int = 0
@objc dynamic var name : String?
override class func primaryKey() -> String? {
return "id"
}
private enum CodingKeys: String, CodingKey {
case id
case name
}
}