如何使用 RealmSwift 存储字典?
How can I store a Dictionary with RealmSwift?
考虑以下模型:
class Person: Object {
dynamic var name = ""
let hobbies = Dictionary<String, String>()
}
我正在尝试在 Realm 中存入一个类型为 [String:String]
的对象,该对象是我从 Alamofire 请求中获得的,但不能,因为 hobbies
必须 根据 RealmSwift 文档通过 let
定义,因为它是 List<T>
/Dictionary<T,U>
类型。
let hobbiesToStore: [String:String]
// populate hobbiestoStore
let person = Person()
person.hobbies = hobbiesToStore
我也尝试重新定义 init()
但总是以致命错误结束,否则。
如何在 RealSwift 中简单地复制或初始化字典?
我是不是遗漏了一些微不足道的东西?
Dictionary
在 Realm 中不支持 属性 类型。
您需要引入一个新的 class,其对象分别描述一个键值对和一对多关系,如下所示:
class Person: Object {
dynamic var name = ""
let hobbies = List<Hobby>()
}
class Hobby: Object {
dynamic var name = ""
dynamic var descriptionText = ""
}
对于反序列化,您需要将 JSON 中的字典结构映射到 Hobby 对象,并将键和值分配给适当的 属性。
可能有点低效,但对我有用(来自 Int->String 的示例字典,类似于您的示例):
class DictObj: Object {
var dict : [Int:String] {
get {
if _keys.isEmpty {return [:]} // Empty dict = default; change to other if desired
else {
var ret : [Int:String] = [:];
Array(0..<(_keys.count)).map{ ret[_keys[[=10=]].val] = _values[[=10=]].val };
return ret;
}
}
set {
_keys.removeAll()
_values.removeAll()
_keys.appendContentsOf(newValue.keys.map({ IntObj(value: [[=10=]]) }))
_values.appendContentsOf(newValue.values.map({ StringObj(value: [[=10=]]) }))
}
}
var _keys = List<IntObj>();
var _values = List<StringObj>();
override static func ignoredProperties() -> [String] {
return ["dict"];
}
}
Realm 无法存储 Strings/Ints 的列表,因为它们不是对象,所以 "fake objects":
class IntObj: Object {
dynamic var val : Int = 0;
}
class StringObj: Object {
dynamic var val : String = "";
}
受这里关于堆栈溢出的另一个答案的启发,用于类似地存储数组(post 目前正在躲避我)...
我目前正在模拟这个,方法是在我的模型上公开一个被忽略的字典属性,由一个私有的、持久的NSData支持,它封装了一个JSON表示字典数:
class Model: Object {
private dynamic var dictionaryData: NSData?
var dictionary: [String: String] {
get {
guard let dictionaryData = dictionaryData else {
return [String: String]()
}
do {
let dict = try NSJSONSerialization.JSONObjectWithData(dictionaryData, options: []) as? [String: String]
return dict!
} catch {
return [String: String]()
}
}
set {
do {
let data = try NSJSONSerialization.dataWithJSONObject(newValue, options: [])
dictionaryData = data
} catch {
dictionaryData = nil
}
}
}
override static func ignoredProperties() -> [String] {
return ["dictionary"]
}
}
这可能不是最有效的方法,但它允许我继续使用 Unbox 快速轻松地将传入的 JSON 数据映射到我的本地 Realm 模型。
我会在 Realm 中将字典保存为 JSON 字符串。然后检索 JSON 并转换为字典。使用以下扩展。
extension String{
func dictionaryValue() -> [String: AnyObject]
{
if let data = self.data(using: String.Encoding.utf8) {
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject]
return json!
} catch {
print("Error converting to JSON")
}
}
return NSDictionary() as! [String : AnyObject]
} }
和
extension NSDictionary{
func JsonString() -> String
{
do{
let jsonData: Data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String.init(data: jsonData, encoding: .utf8)!
}
catch
{
return "error converting"
}
}
}
2021 年更新
从 Realm 10.8.0 开始,可以使用 Map
类型在 Realm 对象中存储字典。
示例来自 official documentation:
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var currentCity = ""
// Map of city name -> favorite park in that city
let favoriteParksByCity = Map<String, String>()
}
考虑以下模型:
class Person: Object {
dynamic var name = ""
let hobbies = Dictionary<String, String>()
}
我正在尝试在 Realm 中存入一个类型为 [String:String]
的对象,该对象是我从 Alamofire 请求中获得的,但不能,因为 hobbies
必须 根据 RealmSwift 文档通过 let
定义,因为它是 List<T>
/Dictionary<T,U>
类型。
let hobbiesToStore: [String:String]
// populate hobbiestoStore
let person = Person()
person.hobbies = hobbiesToStore
我也尝试重新定义 init()
但总是以致命错误结束,否则。
如何在 RealSwift 中简单地复制或初始化字典? 我是不是遗漏了一些微不足道的东西?
Dictionary
在 Realm 中不支持 属性 类型。
您需要引入一个新的 class,其对象分别描述一个键值对和一对多关系,如下所示:
class Person: Object {
dynamic var name = ""
let hobbies = List<Hobby>()
}
class Hobby: Object {
dynamic var name = ""
dynamic var descriptionText = ""
}
对于反序列化,您需要将 JSON 中的字典结构映射到 Hobby 对象,并将键和值分配给适当的 属性。
可能有点低效,但对我有用(来自 Int->String 的示例字典,类似于您的示例):
class DictObj: Object {
var dict : [Int:String] {
get {
if _keys.isEmpty {return [:]} // Empty dict = default; change to other if desired
else {
var ret : [Int:String] = [:];
Array(0..<(_keys.count)).map{ ret[_keys[[=10=]].val] = _values[[=10=]].val };
return ret;
}
}
set {
_keys.removeAll()
_values.removeAll()
_keys.appendContentsOf(newValue.keys.map({ IntObj(value: [[=10=]]) }))
_values.appendContentsOf(newValue.values.map({ StringObj(value: [[=10=]]) }))
}
}
var _keys = List<IntObj>();
var _values = List<StringObj>();
override static func ignoredProperties() -> [String] {
return ["dict"];
}
}
Realm 无法存储 Strings/Ints 的列表,因为它们不是对象,所以 "fake objects":
class IntObj: Object {
dynamic var val : Int = 0;
}
class StringObj: Object {
dynamic var val : String = "";
}
受这里关于堆栈溢出的另一个答案的启发,用于类似地存储数组(post 目前正在躲避我)...
我目前正在模拟这个,方法是在我的模型上公开一个被忽略的字典属性,由一个私有的、持久的NSData支持,它封装了一个JSON表示字典数:
class Model: Object {
private dynamic var dictionaryData: NSData?
var dictionary: [String: String] {
get {
guard let dictionaryData = dictionaryData else {
return [String: String]()
}
do {
let dict = try NSJSONSerialization.JSONObjectWithData(dictionaryData, options: []) as? [String: String]
return dict!
} catch {
return [String: String]()
}
}
set {
do {
let data = try NSJSONSerialization.dataWithJSONObject(newValue, options: [])
dictionaryData = data
} catch {
dictionaryData = nil
}
}
}
override static func ignoredProperties() -> [String] {
return ["dictionary"]
}
}
这可能不是最有效的方法,但它允许我继续使用 Unbox 快速轻松地将传入的 JSON 数据映射到我的本地 Realm 模型。
我会在 Realm 中将字典保存为 JSON 字符串。然后检索 JSON 并转换为字典。使用以下扩展。
extension String{
func dictionaryValue() -> [String: AnyObject]
{
if let data = self.data(using: String.Encoding.utf8) {
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject]
return json!
} catch {
print("Error converting to JSON")
}
}
return NSDictionary() as! [String : AnyObject]
} }
和
extension NSDictionary{
func JsonString() -> String
{
do{
let jsonData: Data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String.init(data: jsonData, encoding: .utf8)!
}
catch
{
return "error converting"
}
}
}
2021 年更新
从 Realm 10.8.0 开始,可以使用 Map
类型在 Realm 对象中存储字典。
示例来自 official documentation:
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var currentCity = ""
// Map of city name -> favorite park in that city
let favoriteParksByCity = Map<String, String>()
}