2017-08-03 2 views
0

ont des classes Paramètres, Appareil et Attributs:Impossible de mettre à jour le contenu d'un RealmSwift.List avec un autre

class SettingType: CustomStringConvertible { 
    let key: Attributes.Keys 

    init(key: Attributes.Keys) { 
     self.key = key 
    } 

    var name: String? { 
     return self.key.description 
    } 

    var description: String { 
     return "no value in SettingsType" 
    } 
} 

class Setting<T>: SettingType { 
    var value: T 

    init(key: Attributes.Keys, value: T) { 
     self.value = value 
     super.init(key: key) 
    } 

    override var description: String { 
     guard let descriptible = value as? CustomStringConvertible else { 
      return "value has not description" 
     } 
     return descriptible.description 
    } 
} 

class Device: Object, Mappable, Extensible { 
    override static func primaryKey() -> String? { 
     return "id" 
    } 

    var id = RealmOptional<Int>() 
    dynamic var attributes: Attributes! 
    dynamic var name: String! 
    dynamic var phone: String! 
    dynamic var uniqueId: String! 
    dynamic var category: String? 
    dynamic var contact: String? 
    let geofenceIds = RealmSwift.List<Integer>() 
    let groupId = RealmOptional<Int>() 
    dynamic var lastUpdate: String? 
    dynamic var model: String? 
    let positionId = RealmOptional<Int>() 
    dynamic var status: String? 
    dynamic var photo: Data? 

    convenience init(id: Int? = nil, attributes: Attributes = Attributes.empty, name: String, phone: String, uniqueId: String) { 
     self.init() 
     self.id.value = id 
     self.attributes = attributes 
     self.name = name 
     self.phone = phone 
     self.uniqueId = uniqueId 
    } 

    required convenience init?(map: Map) { 
     self.init() 
    } 

    func mapping(map: Map) { 
     id.value   <- map["id"] 
     attributes   <- map["attributes"] 
     name    <- map["name"] 
     phone    <- map["phone"] 
     uniqueId   <- map["uniqueId"] 
     category   <- map["category"] 
     contact    <- map["contact"] 
     geofenceIds   <- map["geofenceIds"] 
     groupId.value  <- map["groupId"] 
     lastUpdate   <- map["lastUpdate"] 
     model    <- map["model"] 
     positionId.value <- map["positionId"] 
     status    <- map["status"] 
    } 
} 

extension Device { 
    var settings: [SettingType] { 
     get { 
      var result = [SettingType]() 
      for key in Attributes.Keys.settings { 
       switch key { 
       case .showOnMap   : 
        result.append(Setting<Bool>(key: key, value: self.attributes.showOnMap)) 
       case .observers   : 
        result.append(Setting<RealmSwift.List<Observer>>(key: key, value: self.attributes.listObservers)) 
       case .trackingMode  : 
        guard let trackMode = self.attributes.trackingMode else { 
         result.append(Setting<TrackMode>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<TrackMode>(key: key, value: trackMode)) 
       case .timeZone   : 
        guard 
         let rawTimeZone = self.attributes.rawTimeZone, 
         let timeZone = TimeZone(rawValue: rawTimeZone) 
         else { 
          result.append(Setting<TimeZone>.defaultValue(for: key)!) 
          break 
        } 
        result.append(Setting<TimeZone>(key: key, value: timeZone)) 
       case .language   : 
        guard let language = self.attributes.language else { 
         result.append(Setting<Language>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<Language>(key: key, value: language)) 
       case .sosContacts  : 
        result.append(Setting<RealmSwift.List<Contact>>(key: key, value: self.attributes.listSosContacts)) 
       case .favoriteContacts : 
        result.append(Setting<RealmSwift.List<Contact>>(key: key, value: self.attributes.listFavoriteContacts)) 
       case .alarms   : 
        result.append(Setting<RealmSwift.List<Alarm>>(key: key, value: self.attributes.listAlarms)) 
       case .silentMode  : 
        result.append(Setting<RealmSwift.List<SilentInterval>>(key: key, value: self.attributes.listSilentMode)) 
       case .pedometer   : 
        result.append(Setting<Bool>(key: key, value: self.attributes.pedometer)) 
       case .watchBattery  : 
        result.append(Setting<Bool>(key: key, value: self.attributes.watchBattery)) 
       case .notifyOnRemoval : 
        result.append(Setting<Bool>(key: key, value: self.attributes.notifyOnRemoval)) 
       case .settingModel  : 
        guard let model = self.model else { 
         result.append(Setting<String>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<String>(key: key, value: model)) 
       case .settingPhone  : 
        guard let phone = self.phone else { 
         result.append(Setting<String>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<String>(key: key, value: phone)) 
       case .settingUniqueId : 
        guard let uniqueId = self.uniqueId else { 
         result.append(Setting<String>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<String>(key: key, value: uniqueId)) 
       case .settingName  : 
        guard let name = self.name else { 
         result.append(Setting<String>.defaultValue(for: key)!) 
         break 
        } 
        result.append(Setting<String>(key: key, value: name)) 
       default     : break 
       } 
      } 
      return result 
     } 
     set { 
      for setting in newValue { 
       switch setting.key { 
       case .showOnMap   : self.attributes.showOnMap = (setting as! Setting<Bool>).value 

       case .observers   : 
        self.attributes.listObservers.removeAll() 
        self.attributes.listObservers.append(objectsIn: (setting as! Setting<RealmSwift.List<Observer>>).value) 

       case .sosContacts  : 
        self.attributes.listSosContacts.removeAll() 
        self.attributes.listSosContacts.append(objectsIn: (setting as! Setting<RealmSwift.List<Contact>>).value) 

       case .favoriteContacts : 
        self.attributes.listFavoriteContacts.removeAll() 
        self.attributes.listFavoriteContacts.append(objectsIn: (setting as! Setting<RealmSwift.List<Contact>>).value) 

       case .alarms   : 
        self.attributes.listAlarms.removeAll() 
        self.attributes.listAlarms.append(objectsIn: (setting as! Setting<RealmSwift.List<Alarm>>).value) 

       case .silentMode  : 
        self.attributes.listSilentMode.removeAll() 
        self.attributes.listSilentMode.append(objectsIn: (setting as! Setting<RealmSwift.List<SilentInterval>>).value) 

       case .trackingMode  : self.attributes.trackingMode = (setting as! Setting<TrackMode>).value 
       case .timeZone   : self.attributes.rawTimeZone = (setting as! Setting<TimeZone>).value.rawValue 
       case .language   : self.attributes.language = (setting as! Setting<Language>).value 
       case .pedometer   : self.attributes.pedometer = (setting as! Setting<Bool>).value 
       case .watchBattery  : self.attributes.watchBattery = (setting as! Setting<Bool>).value 
       case .notifyOnRemoval : self.attributes.notifyOnRemoval = (setting as! Setting<Bool>).value 
       case .settingModel  : self.model = (setting as! Setting<String>).value 
       case .settingPhone  : self.phone = (setting as! Setting<String>).value 
       case .settingUniqueId : self.uniqueId = (setting as! Setting<String>).value 
       case .settingName  : self.name = (setting as! Setting<String>).value 
       default     : break 
       } 
      } 
     } 
    } 
} 

class Attributes: Object, Mappable { 
    static let empty = Attributes() 

    enum Keys: String { 
     case showOnMap 
     case observers 
     case trackingMode 
     case timeZone 
     case language 
     case sosContacts 
     case favoriteContacts 
     case alarms 
     case silentMode 
     case pedometer 
     case watchBattery 
     case notifyOnRemoval 
     case settingModel 
     case settingPhone 
     case settingUniqueId 
     case settingName 
     case emptySetting 

     case modified 

     case sat 
     case rssi 
     case battery 
     case steps 
     case ip 
     case distance 
     case totalDistance 

     static let settings: [Keys] = [.showOnMap, .observers, .trackingMode, .timeZone, .language, .sosContacts, .favoriteContacts, .alarms, .silentMode, .pedometer, .watchBattery, .notifyOnRemoval, .settingModel, .settingPhone, .settingUniqueId, .settingName] 

    let sat = RealmOptional<Int>() 
    let rssi = RealmOptional<Int>() 
    dynamic var battery: String? 
    let steps = RealmOptional<Int>() 
    dynamic var ip: String? 
    let distance = RealmOptional<Double>() 
    let totalDistance = RealmOptional<Double>() 

    dynamic var showOnMap = false 

    dynamic var rawTrackingMode: String? 
    var trackingMode: TrackMode? { 
     set { 
      guard 
       let newValue = newValue 
       else { 
        self.rawTrackingMode = nil 
        return 
      } 
      self.rawTrackingMode = newValue.rawValue 
     } 
     get { 
      guard 
       let rawTrackingMode = self.rawTrackingMode, 
       let trackMode = TrackMode(rawValue: rawTrackingMode) 
       else { 
        return nil 
      } 
      return trackMode 
     } 
    } 

    dynamic var rawTimeZone: String? 

    dynamic var rawLanguage: String? 
    var language: Language? { 
     set { 
      guard let newValue = newValue else { 
       self.rawLanguage = nil 
       return 
      } 
      self.rawLanguage = newValue.rawValue 
     } 
     get { 
      guard 
       let rawLanguage = self.rawLanguage, 
       let language = Language(rawValue: rawLanguage) 
       else { 
        return nil 
      } 
      return language 
     } 
    } 

    let listObservers = RealmSwift.List<Observer>() 
    let listSosContacts = RealmSwift.List<Contact>() 
    let listFavoriteContacts = RealmSwift.List<Contact>() 
    let listAlarms = RealmSwift.List<Alarm>() 
    let listSilentMode = RealmSwift.List<SilentInterval>() 

    dynamic var pedometer = false 
    dynamic var watchBattery = false 
    dynamic var notifyOnRemoval = false 

    dynamic var modified: String? 

    dynamic var alarm: String? 

    required convenience init?(map: Map) { 
     self.init() 
    } 

    func mapping(map: Map) { 
     sat.value   <- map[Keys.sat.rawValue] 
     rssi.value   <- map[Keys.rssi.rawValue] 
     battery    <- map[Keys.battery.rawValue] 
     steps.value   <- map[Keys.steps.rawValue] 
     ip     <- map[Keys.ip.rawValue] 
     distance.value  <- map[Keys.distance.rawValue] 
     totalDistance.value <- map[Keys.totalDistance.rawValue] 
     showOnMap   <- map[Keys.showOnMap.rawValue] 

     listObservers   <- map[Keys.observers.rawValue] 
     listAlarms    <- map[Keys.alarms.rawValue] 
     listSosContacts   <- map[Keys.sosContacts.rawValue] 
     listFavoriteContacts <- map[Keys.favoriteContacts.rawValue] 
     listSilentMode   <- map[Keys.silentMode.rawValue] 

     trackingMode  <- (map[Keys.trackingMode.rawValue], EnumTransform<TrackMode>()) 
     rawTimeZone   <- map[Keys.timeZone.rawValue] 
     language   <- (map[Keys.language.rawValue], EnumTransform<Language>()) 
     pedometer   <- map[Keys.pedometer.rawValue] 
     watchBattery  <- map[Keys.watchBattery.rawValue] 
     notifyOnRemoval  <- map[Keys.notifyOnRemoval.rawValue] 
     modified   <- map[Keys.modified.rawValue] 
     alarm    <- map["alarm"] 
    } 
} 

Le problème est, lorsque je tente des attributs de mise à jour du périphérique à l'aide « Interface Paramètres »:

func updateSettings(of device: Device, settings: [SettingType], handler: ((Device) -> Void)? = nil) { 
    do { 
     try RealmManager.shared.realm.write { 
      device.settings = settings 
     } 
     handler?(device) 
    } catch { 
     self.fail(with: error) 
    } 
} 

listes dans les attributs de mises à jour de périphériques de manière incorrecte, je vais perdre des données de listes inchangées. Peut-être un problème est que les listes contiennent aussi des objets gérés par le royaume (Observer, Alarm, Contact, SilentInterval) mais ils n'ont pas de clés primaires?

Toute aide sera grandement appréciée.

MISE À JOUR 1: Trouvé "bug", quand je supprime tous les objets de la "vieille" liste, il supprime également tous les objets de "nouveau" ... Mais pourquoi? Et comment s'en débarrasser?

Répondre

1

Puisque les classes sont reference types, lorsque vous écrivez let newList = oldList, où oldList est un Realm List, vous ne copiez pas le contenu de la liste, vous venez de copier une référence. Cela signifie que les deux newList et oldList pointeront vers les mêmes objets en mémoire et donc si vous modifiez l'un d'eux, les deux seront modifiés.

Pour copier toutes les valeurs de oldList dans newList, vous pouvez créer des copies non gérés des objets oldList et les stocker dans newList en utilisant

let newList = oldList.map{Setting(value:$0)}

De cette façon, les changements que vous appliquez à l'un de vos les listes ne seront pas reflétées sur l'autre liste.

+0

Merci, je l'ai déjà trouvé, mais merci quand même! Découvert que Realm n'est pas une option pour mon projet btw – zzheads

+1

Pas de soucis. Le royaume est un excellent cadre, mais bien sûr ce n'est pas la bonne façon de procéder pour chaque projet. J'espère que vous trouverez une alternative plus adaptée à votre projet. –