Подтвердить что ты не робот

Как я могу хранить словарь с помощью RealmSwift?

Учитывая следующую модель:

class Person: Object {
    dynamic var name = ""
    let hobbies = Dictionary<String, String>()
}

Я пытаюсь создать в Realm объект типа [String:String], который я получил из запроса Alamofire, но не могу, поскольку hobbies должен быть определен через let в соответствии с в RealmSwift Documentation, поскольку это тип типа List<T>/Dictionary<T,U>.

let hobbiesToStore: [String:String]
// populate hobbiestoStore
let person = Person()
person.hobbies = hobbiesToStore

Я также попытался переопределить init(), но всегда получал фатальную ошибку или еще.

Как я могу просто скопировать или инициализировать словарь в RealSwift? Я пропустил что-то тривиальное здесь?

4b9b3361

Ответ 1

Dictionary не поддерживается как тип свойства в Realm. Вам нужно будет ввести новый класс, объекты которого описывают каждое отношение key-value-pair и to-many к такому, как показано ниже:

class Person: Object {
    dynamic var name = ""
    let hobbies = List<Hobby>()
}

class Hobby: Object {
    dynamic var name = ""
    dynamic var descriptionText = ""
}

Для десериализации вам необходимо сопоставить структуру словаря в объектах JSON для хобби и назначить ключ и значение соответствующему свойству.

Ответ 2

В настоящее время я имитирую это, выставляя игнорируемое свойство Dictionary на моей модели, поддерживаемое частной, устойчивой 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.

Ответ 3

Возможно, немного неэффективно, но работает для меня (пример словаря из 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[$0].val] = _values[$0].val };
            return ret;
         }
      }
      set {
         _keys.removeAll()
         _values.removeAll()
         _keys.appendContentsOf(newValue.keys.map({ IntObj(value: [$0]) }))
         _values.appendContentsOf(newValue.values.map({ StringObj(value: [$0]) }))
      }
   }
   var _keys = List<IntObj>();
   var _values = List<StringObj>();

   override static func ignoredProperties() -> [String] {
      return ["dict"];
   }
}

Царство не может хранить список строк/строк, потому что это не объекты, поэтому создайте "поддельные объекты":

class IntObj: Object {
   dynamic var val : Int = 0;
}

class StringObj: Object {
   dynamic var val : String = "";
}

Вдохновленный другим ответом здесь на переполнение стека для хранения массивов аналогично (сообщение ускользает от меня в настоящее время)...

Ответ 4

Я бы сохранил словарь как строку JSON в Realm. Затем загрузите 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"
        }
    }
}