2016-12-21 5 views
0

Es gibt viele sehr ähnliche Fragen auf StackOverflow, aber ich frage das, weil fast jede vorhandene Frage dadurch verursacht wird, performFetch auf dem FRC nicht aufzurufen.NSFetchedResultController ruft controllerDidChangeContent nicht im Delegaten auf

In diesem Fall nennen wir es.

fetchedResultsController = NSFetchedResultsController(fetchRequest: StepRecord.fetchRequest(forDate: date), 
               managedObjectContext: theMainThreadContext, 
               sectionNameKeyPath: nil, 
                 cacheName: nil) 

fetchedResultsController.delegate = self 

do { 
    try fetchedResultsController.performFetch() 
} catch (let error) { 
    print(error) 
} 

Dann in einer späteren Funktion, wir haben so etwas wie dieses ...

func updateScreen() { 
    if fetchedResultsController.fetchedObjects.count == 0 { 
     // download data and store into core data 
    } 

    // update the screen 
} 

Und wir haben die Delegatmethode ...

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
    updateScreen() 
} 

Der Ort, in schreibt Core-Daten schreiben definitiv in eine backgroundThreadContext (das ist ein Muster, das wir mehrmals in der App verwendet haben und es funktioniert woanders).

Die Delegate-Methode wird in diesem Fall jedoch nicht aufgerufen.

Wenn wir den Bildschirm verlassen und gehen in der updateScreen Methode läuft und der FRC hat Daten. Damit die Abrufanforderung korrekt ist, werden durch den Download Datensätze an der richtigen Stelle abgelegt und ordnungsgemäß gespeichert, und die Aktualisierungsbildschirmmethode kann diese Elemente abrufen und den Bildschirm füllen.

Das einzige Problem, das wir hier haben, ist, dass die Delegate-Methode nicht aufgerufen wird.

Gibt es etwas, was wir hier verpasst haben? Wie ich schon sagte, wir haben das gleiche Muster an einigen Stellen verwendet und es funktioniert. Nur in diesem Fall funktioniert es nicht.

Lassen Sie mich wissen, ob es einen anderen Code gibt, den Sie sehen möchten, und ich werde ihn weitergeben, wenn ich kann.

+0

@ SeanLintern88 AFAIK 'controllerDidChangeContent' enthält auch Zusätze, so dass das Hinzufügen von Daten in der Abrufanforderung die Delegate-Methoden auslösen sollte. – Fogmeister

+0

Sie sagen also, dass die hinzugefügten Daten auch dann ein Update verursachen sollten, wenn die ursprünglichen Daten leer sind? Wenn ja, könnten Sie die Abrufanforderung posten: D 'StepRecord.fetchRequest (forDate: date)' – SeanLintern88

+0

@ SeanLintern88 yep, so funktioniert es. Am Ende funktionierte es. Danke – Fogmeister

Antwort

0

In diesem Fall verwenden Sie einen anderen NSManagedObjectContext zum Speichern der heruntergeladenen Daten. Dieser Kontext verwendet eine Hintergrundwarteschlange, wie Sie sagen. Aber vielleicht ist dieser Kontext kein Kind des Kontexts der FRC. In diesem Fall müssen Sie in den Hauptkontext wechseln, um die Benachrichtigung der anderen Änderung zu hören.

Aber die einfache Möglichkeit, es zu beheben, ist die Verwendung eines Hintergrundkontexts, der ein Kind des Hauptkontexts ist. Erstellen Sie einen neuen Kontext vom Typ privateQueue, und legen Sie den übergeordneten Kontext auf den aktuellen Kontext fest.

+0

Ja, das machen wir. Ich werde es jedoch überprüfen. Thanks – Fogmeister

+0

Beachten Sie, dass wenn Sie einen NSPersistentContainer verwenden und NewBackgroundContext verwenden, dieser Kontext nicht Sohn von ViewContext ist. Und sie werden nicht automatisch zusammengeführt. – Gabriel

+0

Hey, wir haben das Problem nach einer ernsthaften Debug-Sitzung gefunden. Ich habe eine Antwort hinzugefügt. Danke für die Hilfe :) – Fogmeister

0

TL: DR - Objekte, die nicht existieren, werden nicht auf NSNotifications warten.

OK, nach einigen ernsthaften Debugging haben wir endlich das Problem gefunden, das dies verursacht hat und es ist ein doozy.

Also, der Code in meiner Frage bestand innerhalb einer class, die im Wesentlichen ein "Arbeiter" für eine Fabrikklasse war.

Dieser Arbeiter wurde von der Fabrik verwendet, um ein Objekt zu erstellen und es an den Besitzer der Fabrik (den "Verbraucher", wenn Sie möchten) zurückgeben.

Consumer        - view controller 
- Factory        - strongly referenced 
    - Worker       - function variable 
     - FetchedResultsController stuff - strongly referenced 

Während wir einen starken Hinweis auf die Fabrik wurden zu halten, hat die Fabrik nicht speichern tatsächlich einen Verweis auf die Arbeiter außerhalb der Funktion es in verwendet wurde.

Das bedeutet, dass bis zum Abschluss des Downloads und dem Speichern der Daten in CoreData der Fetched Results Controller und der "worker" nicht mehr im Speicher vorhanden waren.

Die einfache Lösung bestand also darin, dem Arbeiter eine gespeicherte Referenz hinzuzufügen.

Die längere Lösung ist es, etwas Code umzugestalten, denke ich, aber das ist ein Job für einen anderen Tag.

Vielen Dank für die Hilfe. Es hat uns definitiv geholfen, das Problem zu beseitigen.

Verwandte Themen