2015-06-10 4 views
7

Ich verwende RealmSwift für mein Projekt. Aber ich bin nicht sicher, wie die folgenden zu bewältigen:RealmSwift RLMException

RMLException: Der Versuch, Objekt außerhalb einer Schreibtransaktion zu ändern - rufen beginWriteTransaction auf einer RLMRealm Instanz erste

geworfen.

Jeder irgendeinen Anhaltspunkt?

import RealmSwift 

func createOrUpdateMachineInRealm(machine: Machine){ 

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT 

    dispatch_async(dispatch_get_global_queue(priority, 0)) { 
     // do some task 
     let realm = Realm() 

     realm.beginWrite() 

     realm.write{ 
      realm.add(machine, update: true) 
     } 

     realm.commitWrite() 

     dispatch_async(dispatch_get_main_queue()) { 
      // update some UI 
      actionDelegate?.operationCompleted(true) 
     } 

    } 
} 

Lösung: Ich gehe für Maschine in den Parametern als auch und ordnen sie in der realm.write an der Maschine()

func createOrUpdateMachineInRealm(machine: Machine, name: String){ 

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT 

    dispatch_async(dispatch_get_global_queue(priority, 0)) { 
     // do some task 
     let realm = Realm() 

     realm.write{ 
      machine.name = name 
      realm.add(machine, update: true) 
     } 
    } 

} 

Antwort

9

Ich hatte gerade das gleiche Problem und die Ausnahme wie Sie. Obwohl die Antwort von Nate Mann nicht die Lösung des Problems ist, führt sie mich in die richtige Richtung.

Sie können ein Realm-Objekt, das Sie zuvor aus der Datenbank gezogen haben, nicht ändern, da Realm versuchen wird, es zu aktualisieren und einen Fehler auszulösen, wenn es (aus welchen Gründen auch immer) in einer anderen Warteschlange ist.

Sie müssen entweder alle Änderungen innerhalb Ihrer realm.write{ } Anweisung vornehmen oder ein neues Objekt mit demselben Primärschlüssel erstellen, damit es korrekt aktualisiert wird. Das würde auch bedeuten, dass Sie keine Funktion haben, um oder Update zu erstellen, aber zwei separate benötigen.

Ihre Update-Funktion würde in etwa so aussehen:

func updateMachineInRealm(machine: Machine){ 
    var updatedMachine = Machine() 
    updatedMachine.name = machine.name 
    updatedMachine.value = machine.value + 42 
    updatedMachine.primaryKey = machine.primaryKey 
    // "transfer" or modify all the values of the old machine object 

    let realm = try! Realm() 
    do { 
     try realm.write() { 
     realm.add(updatedMachine, update: true) 
    } 
} 

Denken Sie daran, dass Sie einen eindeutigen Primärschlüssel für diesen Code arbeiten müssen, denn das ist, was Realm wird mit Ihrem neues Objekt entspricht in der Datenbank .

Auch das hat natürlich Nachteile bei der Arbeit an einem größeren Projekt mit mehr als einem Thread Zugriff auf Realm Objekte usw. Aber es wird für kleine Projekte funktionieren (wie ich arbeitete und Sie scheinen zu arbeiten).

5

Sie sich von realm.beginWrite() und realm.commitWrite() befreien. Sie werden nicht benötigt, wenn Sie realm.write { } verwenden.

+0

Danke für die Antwort @NateMann. Ich kann es das erste Mal ohne Fehler hinzufügen. Allerdings habe ich diese '*** Terminating App aufgrund der nicht abgefangenen Ausnahme 'RLMException', Grund: 'Versuch, das Objekt außerhalb einer Schreibtransaktion zu ändern - rufe zuerst beginWriteTransaction auf einer RLMRealm-Instanz auf.' 'Wenn ich die Methode erneut aufrufen (z aktualisieren). – perwyl

+1

Fügen Sie eine Maschine hinzu oder aktualisieren Sie eine. Wenn du eines aktualisierst, mach machine.name = "Drill", muss dies in Realm() gemacht werden. Schreibe {}, wie dieses Realm(). Write {machine.name = "Drill"} –

+0

Ist das möglich? ich das Machine-Objekt auf UI-Ebene aktualisieren und an Realm() (Storage.swift) für die Schreibtransaktion übergeben? Ich versuche, Realm bei den ViewControllern zu vermeiden. Sehr neu bei realmSwift – perwyl

Verwandte Themen