2

Die Apple-Dokumentation ist nicht klar (oder ich finde es nicht) auf, was passiert im Fall eines Eltern- und Kind-MOC, wenn das Eltern-MOC Einsätze gefolgt von Speichern hat.NSManagedObjectContext - Wie aktualisiert man das Kind, wenn sich der Elternteil ändert?

Ich benutze MARCUS ZARRA http://martiancraft.com/blog/2015/03/core-data-stack/ Methode, mit einem privatenQMOC an der Spitze und der childMainMOC als Hauptthread eins.

Problem

ich hinzufügen 10.000 Objekte in die privateMOC über eine Hintergrund Internet-Anfrage (s) speichert auf dem privateMOC Aufruf, aber alle auf dem childMainMOC Kontext gebaut NSFetchedResultsControllers nie meinen Delegaten nennen, nachdem die Eltern speichern. Daher wird die Schnittstelle nicht aktualisiert, um Änderungen in der parentMOC anzuzeigen.

Ich möchte etwas aufrufen, das alle Objekte in der ChildMainMOC aktualisieren wird - die dann die Delegate-Methoden auf dem untergeordneten Controller aufrufen sollte.

Oder eine andere Lösung.

Antwort

1

Schlüsselinformation:

Der Rest der Kontexte werden die Kinder der Haupt Queue Kontext sein

So Ihrem Kontext die heruntergeladenen Daten zur Verarbeitung muss ein Kind des Haupt Kontext sein Wenn Sie das Kind speichern, speichern Sie den Hauptkontext und speichern den persistenten Kontext.

Wenn Sie den Datenverarbeitungskontext speichern, benachrichtigt er sofort den übergeordneten Thread, den Hauptthreadkontext, aber Sie benötigen immer noch 2 Sicherungen, um die Daten auf die Festplatte zu bekommen.

+0

Keine seiner andersrum . Der privateMOC ist die Wurzel, dies ermöglicht eine bessere Leistung und wird auch aus anderen Gründen benötigt. Ich benutze nur 2 MOCs das private root one und das Kind eines, das ein Hauptthread ist. –

+0

dann folgen Sie nicht der Anleitung der Seite, auf die Sie verlinken ...Wenn Sie Ihren Ansatz verwenden, müssen Sie die Änderungen nach dem Speichern in den Hauptkontext zusammenführen. Das passiert nicht automatisch. – Wain

+0

Ich sehe - Marcus Zarras Seite hat ein privateQ im Wurzelverzeichnis. Er hat dann eine mainThreadQ darunter. Das mache ich also. Aber rät mehrere Privatpersonen unterhalb dieser Hauptleitung, was zu echten Leistungsproblemen in einem Setup führt, bei dem die meisten der Daten, die in das System kommen, von Nicht-Benutzereingaben stammen. –

1

Ok - also habe ich alles herausgefunden.

Das Modell ist wie in: Marcus Zarra des http://martiancraft.com/blog/2015/03/core-data-stack/ Die privateMOC an der Wurzel ist, das für eine bessere Leistung ermöglicht und auch auf diese Weise aus anderen Gründen erforderlich ist. Ich benutze nur 2 MOCs: das private root one und das child one, das ein Haupt-Thread ist.

dies Dann lesen: Grundsätzlich erklärt er, wie Core Data-Benachrichtigungen Griffe usw. http://benedictcohen.co.uk/blog/archives/308

THEN - das letzte, was ich tun musste: alle ObjectIDs im Programm stellen Sie sicher, echte Dauer diejenigen sind.

- (id)insertNewObjectForEntityName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context { 

NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context]; 

// Make sure all inserted objects have a permanent ID. 
// THIS IS VITAL. Without getting the permanentIDs, changes that come in from the web will not propogate to the child mainQ MOC and the UI will not update. 
// Tested to be performant. 
//NSLog(@"testing this - object.objectID is a temp now I think: %@ isTemp:%d", object.objectID, (int) [object.objectID isTemporaryID]); 
// http://stackoverflow.com/questions/11990279/core-data-do-child-contexts-ever-get-permanent-objectids-for-newly-inserted-obj 
NSError* error = nil; 
[context obtainPermanentIDsForObjects:@[object] error:&error]; 
if (error || [object.objectID isTemporaryID]) 
    NSLog(@"obtainPermanentIDsForObjects is NOT WORkING - FIX: a new %@ isTemp: %d !!", entityName, (int) [object.objectID isTemporaryID]); 

return object; 

}

Auch musste ich laut Benedicts Artikel - für Änderungen im Stamm privaten MOC Eltern hören

/// . http://benedictcohen.co.uk/blog/archives/308 good info ! 
/// I need this firing as sometimes objects change and the save notification below is not enough to make sure the UI updates. 
- (void)privateQueueObjectContextDidChangeNotification:(NSNotification *)notification { 
    NSManagedObjectContext *changedContext = notification.object; 
    NSManagedObjectContext *childContext = self.mainQueueObjectContext; 
    BOOL isParentContext = childContext.parentContext == changedContext; 
    if (!isParentContext) return; 

    //Collect the objectIDs of the objects that changed 
    __block NSMutableSet *objectIDs = [NSMutableSet set]; 
    [changedContext performBlockAndWait:^{ 
     NSDictionary *userInfo = notification.userInfo; 
     for (NSManagedObject *changedObject in userInfo[NSUpdatedObjectsKey]) { 
      [objectIDs addObject:changedObject.objectID]; 
     } 
     for (NSManagedObject *changedObject in userInfo[NSInsertedObjectsKey]) { 
      [objectIDs addObject:changedObject.objectID]; 
     } 
     for (NSManagedObject *changedObject in userInfo[NSDeletedObjectsKey]) { 
      [objectIDs addObject:changedObject.objectID]; 
     }  
    }]; 

    //Refresh the changed objects 
    [childContext performBlock:^{ 
     for (NSManagedObjectID *objectID in objectIDs) { 
      NSManagedObject *object = [childContext existingObjectWithID:objectID error:nil]; 
      if (object) { 
       [childContext refreshObject:object mergeChanges:YES]; 
       //NSLog(@"refreshing %@", [object description]); 
      } 
     } 
    }]; 
} 
    - (void)privateQueueObjectContextDidSaveNotification:(NSNotification *)notification { 
    //NSLog(@"private Q MOC has saved"); 
    [self.mainQueueObjectContext performBlock:^{ 
     [self.mainQueueObjectContext mergeChangesFromContextDidSaveNotification:notification]; 
     // I had UI update problems which I fixed with mergeChangesFromContextDidSaveNotification along with obtainPermanentIDsForObjects: in the insertEntity call. 
    }]; 

}

/// When the MainMOC saves - the user has changed data. 
/// We save up into the privateQ as well at this point. 
- (void)mainQueueObjectContextDidSaveNotification:(NSNotification *)notification { 
    NSLog(@"main Q MOC has saved - UI level only changes only please"); 
    [self.privateQueueObjectContext performBlock:^{ 
     NSError* error = nil; 
     if (self.privateQueueObjectContext.hasChanges) { 
      [self.privateQueueObjectContext save:&error]; 
      if (error) 
      { 
       NSLog(@"Save up error - the actual datastore was not updated : %@", error); 
      } 
     } else { 
      //NSLog(@"No need to save"); 
     } 
    }]; 
}