避免领域数据库中自定义对象数组的重复。当主键仅存在于关系 table 中时
Avoid duplication in array of custom object in realm database. When Primary key is exist in the relational table only
如何避免领域数据库中自定义对象数组的重复,下面是我的代码和相关的JSON如果我在模型中做错了,请纠正我。
JSON ->
{
"playlists": [
{
"id": "1f23bd3e-cc01-11e8-b25e-784f435e4a9a",
"name": "disney nostalgia",
"duration": 361,
},
{
"id": "2e1f0e02-cc05-11e8-9efe-784f435e4a9a",
"name": "songs from aladdin",
"duration": 331,
}
],
"tracks": [
{
"id": "3e986a2a-cc01-11e8-bb04-784f435e4a9a",
"name": "I'll Make a Man Out of You",
"artist": "Donny Osmond & Chorus"
},
{
"id": "aff8bcee-cc04-11e8-8c18-784f435e4a9a",
"name": "A Whole New World",
"artist": "Lea Salonga, Brad Kane"
}
]
}
型号如下
class Songs: Object, Codable {
let playlists = List<Playlists>()
let tracks = List<Tracks>()
enum CodingKeys: String, CodingKey {
case playlists
case tracks
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
if let playLists = try container.decodeIfPresent([Playlists].self, forKey: .playlists){
playLists.forEach({self.playlists.append([=12=])})
}
if let tracksList = try container.decodeIfPresent([Tracks].self, forKey: .tracks){
tracksList.forEach({self.tracks.append([=12=])})
}
}
func encode(to encoder: Encoder) throws {
//
}
}
class Playlists: Object, Codable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var duration: Int = 0
enum CodingKeys: String, CodingKey {
case id
case name
case duration
}
override static func primaryKey() -> String? {
return "id"
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.duration = try container.decode(Int.self, forKey: .duration)
}
}
class Tracks: Object, Codable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var artist: Int = 0
enum CodingKeys: String, CodingKey {
case id
case name
case artist
}
override static func primaryKey() -> String? {
return "id"
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.artist = try container.decode(Int.self, forKey: .artist)
}
}
这就是我保存数据的方式。
SongsData = try jsonDecoder.decode(Songs.self, from: data)
let realm = try! Realm()
try! realm.write {
realm.add(SongsData)
} catch {
Logger.log.printOnConsole(string: "Unable to convert to data")
}
当服务器响应相同时,如何避免数据重复。
在将对象添加到 List
之前,您可以只使用 Set
删除重复项。只需确保您的类型符合要添加到 Set
.
的 Hashable
一些一般性建议:当 属性 名称与 JSON 键匹配时,您不需要创建 CodingKeys
除非您创建自定义 init(from decoder:)
方法并且您不需要创建自定义 init(from:)
方法,除非您执行一些自定义操作,例如使用 decodeIfPresent
和过滤重复对象。对于 Playlists
和 Tracks
,您可以依赖合成初始化器。
您也不需要在循环中将数组中的元素添加到 List
,只需使用 append(objectsIn:)
,它接受 Sequence
作为其输入参数。
class Songs: Object, Decodable {
let playlists = List<Playlists>()
let tracks = List<Tracks>()
enum CodingKeys: String, CodingKey {
case playlists, tracks
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
if let playLists = try container.decodeIfPresent([Playlists].self, forKey: .playlists){
let uniquePlaylists = Set(playLists)
self.playlists.append(objectsIn: uniquePlaylists)
}
if let tracksList = try container.decodeIfPresent([Tracks].self, forKey: .tracks){
let uniqueTrackList = Set(tracksList)
self.tracks.append(objectsIn: uniqueTrackList)
}
}
}
class Playlists: Object, Codable, Hashable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var duration: Int = 0
override static func primaryKey() -> String? {
return "id"
}
}
class Tracks: Object, Codable, Hashable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var artist: Int = 0
override static func primaryKey() -> String? {
return "id"
}
}
如果您想确保不向 Realm
添加任何对象两次,您需要使用 add(_:,update:)
而不是 add
并使用 primaryKey
以避免添加具有相同键的元素。
SongsData = try jsonDecoder.decode(Songs.self, from: data)
let realm = try! Realm()
try! realm.write {
realm.add(SongsData, update: true)
} catch {
Logger.log.printOnConsole(string: "Unable to convert to data")
}
如何避免领域数据库中自定义对象数组的重复,下面是我的代码和相关的JSON如果我在模型中做错了,请纠正我。
JSON ->
{
"playlists": [
{
"id": "1f23bd3e-cc01-11e8-b25e-784f435e4a9a",
"name": "disney nostalgia",
"duration": 361,
},
{
"id": "2e1f0e02-cc05-11e8-9efe-784f435e4a9a",
"name": "songs from aladdin",
"duration": 331,
}
],
"tracks": [
{
"id": "3e986a2a-cc01-11e8-bb04-784f435e4a9a",
"name": "I'll Make a Man Out of You",
"artist": "Donny Osmond & Chorus"
},
{
"id": "aff8bcee-cc04-11e8-8c18-784f435e4a9a",
"name": "A Whole New World",
"artist": "Lea Salonga, Brad Kane"
}
]
}
型号如下
class Songs: Object, Codable {
let playlists = List<Playlists>()
let tracks = List<Tracks>()
enum CodingKeys: String, CodingKey {
case playlists
case tracks
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
if let playLists = try container.decodeIfPresent([Playlists].self, forKey: .playlists){
playLists.forEach({self.playlists.append([=12=])})
}
if let tracksList = try container.decodeIfPresent([Tracks].self, forKey: .tracks){
tracksList.forEach({self.tracks.append([=12=])})
}
}
func encode(to encoder: Encoder) throws {
//
}
}
class Playlists: Object, Codable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var duration: Int = 0
enum CodingKeys: String, CodingKey {
case id
case name
case duration
}
override static func primaryKey() -> String? {
return "id"
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.duration = try container.decode(Int.self, forKey: .duration)
}
}
class Tracks: Object, Codable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var artist: Int = 0
enum CodingKeys: String, CodingKey {
case id
case name
case artist
}
override static func primaryKey() -> String? {
return "id"
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.artist = try container.decode(Int.self, forKey: .artist)
}
}
这就是我保存数据的方式。
SongsData = try jsonDecoder.decode(Songs.self, from: data)
let realm = try! Realm()
try! realm.write {
realm.add(SongsData)
} catch {
Logger.log.printOnConsole(string: "Unable to convert to data")
}
当服务器响应相同时,如何避免数据重复。
在将对象添加到 List
之前,您可以只使用 Set
删除重复项。只需确保您的类型符合要添加到 Set
.
Hashable
一些一般性建议:当 属性 名称与 JSON 键匹配时,您不需要创建 CodingKeys
除非您创建自定义 init(from decoder:)
方法并且您不需要创建自定义 init(from:)
方法,除非您执行一些自定义操作,例如使用 decodeIfPresent
和过滤重复对象。对于 Playlists
和 Tracks
,您可以依赖合成初始化器。
您也不需要在循环中将数组中的元素添加到 List
,只需使用 append(objectsIn:)
,它接受 Sequence
作为其输入参数。
class Songs: Object, Decodable {
let playlists = List<Playlists>()
let tracks = List<Tracks>()
enum CodingKeys: String, CodingKey {
case playlists, tracks
}
required convenience public init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
if let playLists = try container.decodeIfPresent([Playlists].self, forKey: .playlists){
let uniquePlaylists = Set(playLists)
self.playlists.append(objectsIn: uniquePlaylists)
}
if let tracksList = try container.decodeIfPresent([Tracks].self, forKey: .tracks){
let uniqueTrackList = Set(tracksList)
self.tracks.append(objectsIn: uniqueTrackList)
}
}
}
class Playlists: Object, Codable, Hashable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var duration: Int = 0
override static func primaryKey() -> String? {
return "id"
}
}
class Tracks: Object, Codable, Hashable {
@objc dynamic var id: String = ""
@objc dynamic var name: String = ""
@objc dynamic var artist: Int = 0
override static func primaryKey() -> String? {
return "id"
}
}
如果您想确保不向 Realm
添加任何对象两次,您需要使用 add(_:,update:)
而不是 add
并使用 primaryKey
以避免添加具有相同键的元素。
SongsData = try jsonDecoder.decode(Songs.self, from: data)
let realm = try! Realm()
try! realm.write {
realm.add(SongsData, update: true)
} catch {
Logger.log.printOnConsole(string: "Unable to convert to data")
}