2015-06-10 11 views
7

Sto usando RealmSwift per il mio progetto. Tuttavia, non sono sicuro di come affrontare il seguente:RealmSwift RLMException

RMLException: Il tentativo di modificare l'oggetto al di fuori di una transazione di scrittura - chiamano beginWriteTransaction su un RLMRealm un'istanza prima

gettato.

Qualche idea?

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) 
     } 

    } 
} 

Soluzione: mi passa i parametri per la macchina così e assegnarli alla macchina all'interno del realm.write()

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) 
     } 
    } 

} 

risposta

9

Ho appena avuto lo stesso problema ed eccezione come hai fatto tu. Anche se la risposta di Nate Mann non è la soluzione al problema, mi porta nella giusta direzione.

Non è possibile modificare un oggetto di reame precedentemente estratto dal database, poiché Realm tenterà di aggiornarlo e generare un errore, quando è (per qualsiasi motivo) su una coda diversa.

Quindi è necessario eseguire tutte le modifiche all'interno dell'istruzione realm.write{ } o creare un nuovo oggetto con la stessa chiave primaria, in modo che venga aggiornato correttamente. Ciò significherebbe anche che non è possibile avere una funzione per creare l'aggiornamento o, ma sono necessarie due diverse.

tua funzione di aggiornamento dovrebbe essere simile a questa:

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) 
    } 
} 

Ricordate che è necessario una chiave primaria unica per questo codice funzioni, perché questo è ciò Reame abbinerà il vostro nuovo oggetto con nel database .

Inoltre, questo ha naturalmente degli svantaggi quando si lavora a un progetto più grande con più thread che accedono agli oggetti Realm ecc. Ma funzionerà per piccoli progetti (come stavo lavorando e sembra che stiate lavorando).

5

Sbarazzarsi della realm.beginWrite() e realm.commitWrite(). Non sono necessari quando si utilizza realm.write { }.

+0

Grazie per la risposta @NateMann. Sono in grado di aggiungerlo la prima volta senza errori. Tuttavia ho questa applicazione di terminazione a causa dell'eccezione non rilevata RLMException, motivo: "Tentativo di modificare l'oggetto al di fuori di una transazione di scrittura - chiama beginWriteTransaction su un'istanza di RLMRealm first.'' quando chiamo di nuovo il metodo (per aggiornare). – perwyl

+1

Stai aggiungendo una macchina o aggiornandone una. Se si sta aggiornando uno, dire machine.name = "Drill", questo deve essere fatto in Realm(). Write {}, come questo Realm(). Write {machine.name = "Drill"} –

+0

E 'possibile per per aggiornare l'oggetto Machine al livello dell'interfaccia utente e passare a Realm() (Storage.swift) per la transazione di scrittura? Sto cercando di evitare l'utilizzo di Realm su ViewControllers. Molto nuovo a realmSwift – perwyl