2017-01-21 2 views
3

Ich bemerkte viele Probleme mit Realm-Objekt zugreifen, und ich dachte, dass meine Lösung würde das lösen.Realm von falschem Thread zugegriffen - wieder

So habe ich geschrieben einfache Nachschlag Methode wie folgt:

public func write(completion: @escaping (Realm) ->()) { 
    DispatchQueue(label: "realm").async { 
     if let realm = try? Realm() { 
      try? realm.write { 
       completion(realm) 
      } 
     } 
    } 
} 

dachte ich, dass Vollendung Block in Ordnung sein wird, denn jedes Mal wenn ich Objekt schreiben oder aktualisieren, ich diese Methode oben verwenden.

Leider erhalte ich Fehler:

libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread. 
+0

Was macht 'completion'? – EpicPandaForce

Antwort

2

Ihre Methode erstellt ein neues DispatchQueue jedes Mal, wenn Sie es nennen.

DispatchQueue(name:"") ist ein Initialisierer, kein Lookup. Wenn Sie sicherstellen möchten, dass Sie immer in derselben Warteschlange sind, müssen Sie einen Verweis auf diese Warteschlange speichern und an diese Warteschlange senden.

Sie sollten die Warteschlange beim Einrichten des Bereichs erstellen und als eine Eigenschaft der Klasse speichern, die das Setup ausführt.

9

Instanzen von Realm und Object sind Thread-enthalten. Sie können nicht zwischen Threads übergeben werden oder diese Ausnahme wird auftreten.

Da Sie den Block completion zur gleichen Zeit an die Hintergrundwarteschlange übergeben, wenn die Warteschlange erstellt wird (wie Dave Weston sagte), sind Realm-Objekte in diesem Block höchstwahrscheinlich nicht im selben Thread erstellt worden , die diesen Fehler erklären würde.

Wie Dave sagte, erstellen Sie jedes Mal, wenn Sie diese Methode aufrufen, eine neue Dispatch-Warteschlange. Aber um das zu erweitern, gibt es auch keine Garantie von iOS, dass eine einzige Warteschlange konsistent für denselben Thread aufgerufen wird.

Daher empfiehlt es sich, Realm-Objekte in demselben Thread jedes Mal neu zu erstellen, wenn Sie eine neue Operation für diesen Thread ausführen möchten. Realm speichert Instanzen von Realm pro Thread intern, so dass nur ein sehr geringer Aufwand für das mehrfache Aufrufen von Realm() erforderlich ist.

Um ein bestimmtes Objekt zu aktualisieren, können Sie the new ThreadSafeReference feature verwenden, um erneut auf dasselbe Objekt in einem Hintergrundthread zuzugreifen.

let realm = try! Realm() 
let person = Person(name: "Jane") // no primary key required 
try! realm.write { 
    realm.add(person) 
} 
let personRef = ThreadSafeReference(to: person) 
DispatchQueue(label: "com.example.myApp.bg").async { 
    let realm = try! Realm() 
    guard let person = realm.resolve(personRef) else { 
    return // person was deleted 
    } 
    try! realm.write { 
    person.name = "Jane Doe" 
    } 
} 
Verwandte Themen