2015-06-10 11 views
7

Używam dla mojego projektu RealmSwift. Jednak nie jestem pewien, jak rozwiązać następujące:RealmSwift RLMException

RMLException: Próba modyfikacji obiektu poza transakcji zapisu - call beginWriteTransaction na RLMRealm pierwszej

rzucony instancji.

Czy ktoś ma jakąś wskazówkę?

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

    } 
} 

Rozwiązanie: Mijam parametry dla maszyny, jak również i przypisać je do maszyny w 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) 
     } 
    } 

} 

Odpowiedz

9

Po prostu miałem ten sam problem i wyjątek jak ty. Odpowiedź Nate Mann nie jest rozwiązaniem problemu, ale prowadzi mnie we właściwym kierunku.

Nie można zmodyfikować obiektu Realm, który uprzednio wyciągnięto z bazy danych, ponieważ Realm spróbuje go zaktualizować i wygenerować błąd, jeśli jest (z jakiegokolwiek powodu) w innej kolejce.

Musisz więc dokonać wszystkich modyfikacji wewnątrz instrukcji realm.write{ } lub utworzyć nowy obiekt z tym samym kluczem podstawowym, aby był poprawnie aktualizowany. Oznaczałoby to również, że nie możesz mieć jednej funkcji do utworzenia aktualizacji, ale potrzebujesz dwóch oddzielnych.

Twoja funkcja aktualizacji musiałby wyglądać tak:

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

Pamiętaj, że musisz mieć unikalny klucz podstawowy dla tego kodu do pracy, ponieważ to, co Realm dopasuje swój nowy obiekt ze w bazie danych .

Ma to oczywiście również swoje wady podczas pracy nad większym projektem z więcej niż jednym wątkiem, który ma dostęp do obiektów Realm itp. Ale będzie działać w przypadku małych projektów (jak pracowałem i wydaje się, że pracujesz nad).

5

pozbyć realm.beginWrite() i realm.commitWrite(). Nie są potrzebne, gdy używasz realm.write { }.

+0

Dzięki za odpowiedź @NateMann. Jestem w stanie dodać go za pierwszym razem bez błędu. Jednak mam tę '*** aplikację terminującą ze względu na nieprzechwycony wyjątek 'RLMException', powód:" Próba modyfikacji obiektu poza transakcją zapisu - wywołaj beginWriteTransaction na instancji RLMRealm pierwszy ", gdy ponownie wywołasz metodę (dla aktualizacja). – perwyl

+1

Dodajesz maszynę lub ją aktualizujesz. Jeśli aktualizujesz jeden, powiedz machine.name = "Drill", to musisz to zrobić w Realm(). Write {}, jak to Realm(). Napisz {machine.name = "Drill"} –

+0

Czy to możliwe mi zaktualizować obiekt Machine na poziomie interfejsu użytkownika i przekazać do Realm() (Storage.swift) do transakcji zapisu? Próbuję unikać używania Realm w ViewControllers. Bardzo nowy w realmSwift – perwyl