2016-06-27 4 views
0

Ich bin neu in Realm und bekomme einen 'Realm von falschem Thread' Fehler zugegriffen. Ich habe gelesen, dass man auf Daten aus demselben Bereich zugreifen muss, aus dem es abgerufen wurde. Allerdings bekomme ich diesen Fehler, nachdem ich erfolgreich auf das Objekt zugreifen konnte. Hier ist ein Code:Realm - Realm Zugriff von falschem Thread Swift

func retrieveApplicationData(completionBlock: (Results<Application>, NSError?) -> Void) { 
     let realm = try! Realm() 
     let applications = realm.objects(Application) 

     if applications.count > 0 { 
      completionBlock(applications, nil) 
     } 
} 

Diese Methode ruft ein Verfahren, das eine Reihe von Anwendungen zu erstellen, indem Sie: let array = Array(results)

ich dann bin vorbei dies ein Verfahren, das ein Array Sets:

func setApplicationItems(items: [Application]) { 
    applications = items 

    print(applications) 
} 

In der obigen Methode drucke ich das Array und das funktioniert gut. Später im Zyklus wird jedoch die tableViewDatasource-Methode cellForRowAtIndexPath aufgerufen. Hier versuche ich, das Anwendungs-Array zu verwenden, aber die Anwendung stürzt mit dem Fehler 'falscher Thread' ab. Hier ist die Methode:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    print("\(applications)") 

    let cell = ApplicationTableViewCell(style: .Subtitle, reuseIdentifier: nil) 
    let application = applications[indexPath.row] 
    cell.configureCell(application) 

    return cell 
} 

Wie Sie sehen können, habe ich eine Druckanweisung in der oben genannten Methode hinzugefügt. Wenn ich versuche, das Anwendungs-Array hier auszudrucken, bekomme ich den Absturz.

Wie kann ich es in der Methode ausdrucken, die es setzt, aber hier stürzt es ab? Liegt es daran, dass cellForRowAtIndexPath am Haupt-Thread aufgerufen wird? Und wenn ja, wie kann ich meine tableView in diesem Fall aktualisieren? Prost.

========

Edit:

Als ich in cellForRowAtIndexPath folgende bekomme ich wieder ein leeres Ergebnis:

let realm = try! Realm() 
let applicationsB = realm.objects(Application) 

Edit 2:

Ich kümmere mich um die Einsparung in einem Verschluss. Ich habe versucht, es zurück in Haupt-Thread mit dispatch_async übergeben, wenn die Daten zurückgegeben und es immer noch stürzte. Allerdings habe ich diese dispatch_async direkt vor dem Aufruf von self.tableView.ReloadData() verschoben. Es stürzt jetzt nicht ab, was gut ist, aber die Daten sind nicht immer verfügbar. Wenn ich es verlangsame, indem ich Haltepunkte verwende, bekomme ich die Daten zurück. Allerdings sind die Daten nicht da, wenn ich es einfach laufen lasse. Gibt es eine Möglichkeit zu wissen, wann die auf einem Hintergrund-Thread gespeicherten Daten im Haupt-Thread verfügbar sind? Hier

ist der Code, ich verwende:

dispatch_async(dispatch_get_main_queue()) {    
      let realm = try! Realm() 
      realm.refresh() 
      let applicationsB = realm.objects(Application) 
      let array = Array(applicationsB) 
      self.tableViewDataSource.setApplicationItems(array as! [Application]) 
      self.tableView.reloadData() 
     } 

Daten nicht immer da.

bearbeiten 3:

Ich habe jetzt die Speichermethode in einem dispath_async(dispath_get_main_queue()) gewickelt und es funktioniert gut:

dispatch_async(dispatch_get_main_queue()) { 

      let realm = try! Realm() 
      try! realm.write() { 

      let applications = data.map({ (object) -> Application in 
       return Application(applicationID: object.applicationID, contact: "", state: "", jobBoard: object.jobBoard, salary: object.salary, title: object.title, location: "") 
      }) 

      for application in applications { 
       print(application) 
       realm.add(application) 
      } 

      //try! realm.commitWrite() 

      completionBlock(true, nil) 

     } 
+0

Lesen * aufmerksam * was 'https: // Reich .io/docs/swift/latest/# threading sagt über "mehrere Threads." –

+0

Hallo Mike, nachdem ich die Dokumentation gelesen habe, habe ich den Code in meiner vorherigen Bearbeitung ausprobiert, wo ich ein neues Realm erstelle: let realm = try! Realm() und benutze das dann, um meine Objekte abzurufen. Aber das Ergebnis ist leer. Ich habe den Abschnitt, den Sie gesendet haben, noch einmal gelesen und bin mir immer noch nicht sicher, wie ich die Objekte abrufen soll. Ich verstehe es immer noch als: lass Realm = versuchen! Reich(). Fehle ich etwas? – pls

+0

Mit einem Ausnahmeblockpunkt können Sie sehen, welche Zeile Ihres Codes die Ausnahme auslöst, die Realm als Antwort auf seine Threading-Einschränkungen ausgelöst hat. Das sollte das Objekt identifizieren, auf das von dem falschen Thread zugegriffen wird. Sie können dann nachsehen, in welchem ​​Thread das Objekt erstellt wurde und in welchem ​​Thread Sie darauf zugreifen möchten. – bdash

Antwort

0

Edit:

Bitte lesen Kommentar von Bdash unten. Obwohl das funktioniert, ist es nur zufällig. Antwort hier lassen, damit andere nicht dasselbe versuchen.

folgenden Code gearbeitet, aber nicht richtig ist !!!:

So habe ich es geschafft, um es zu arbeiten. Zuerst habe ich die App gestoppt und Code in der Ansicht hinzugefügt, der die Daten abgerufen hat. Das hat gut funktioniert. Also wusste ich, dass die Daten in der Datenbank waren. Allerdings wollte ich die Daten speichern und dann sofort verwenden.

Um dies zu erreichen, musste ich folgende try! realm.commitWrite() in meinem realm.write() { } Block hinzufügen. Vollständige Methode unter:

try realm.write() { 

     let applications = data.map({ (object) -> Application in 
       return Application(applicationID: object.applicationID, contact: "", state: "", jobBoard: object.jobBoard, salary: object.salary, title: object.title, location: "") 
     }) 

     for application in applications { 
      print(application) 
      realm.add(application) 
     } 

     try! realm.commitWrite() // *NOTE* Here is the code I added. 

     completionBlock(true, nil) 

    } 

Einmal habe ich die commitWrite() konnte ich später wie so auf dem Hauptthread meine holen tun:

dispatch_async(dispatch_get_main_queue()) { 

      let realm = try! Realm() 
      realm.refresh() 
      let applicationsB = realm.objects(Application) 
      let array = Array(applicationsB) 

      self.tableViewDataSource.setApplicationItems(array as! [Application]) 


      self.tableView.reloadData() 
     } 
+1

Calling 'commitWrite()' innerhalb des Blocks an 'write()' übergeben ist nicht korrekt. Wenn es passiert, ist es, weil Sie Probleme woanders haben, deren Symptome dies verdunkelt. – bdash