1

Ich bin ein Programm in Swift implementieren und ich verwende das Core Data Framework. Meine App ist fertig, aber ich habe beschlossen, den Core Data Stack umzuformen. Im Augenblick ist die Struktur meiner Core Data Stack sieht wie folgt aus:Core Data Stack Struktur

enter image description here

Ich nahm einen Blick auf die Core Data Stack Form Big Ranch-Nerd und einige andere Jungs auf Github und die meiste Zeit, ihre Core Data Stack sieht wie folgt aus:

enter image description here

ich fragte mich, ob es eine bessere Art und Weise war meine Core Data Stack in ähnlicher Weise zu umgestalten. Auf den Punkt gebracht, ist das, was ich bin mit meiner Managed Object Context für:

  • mainContext = für alle UI-bezogene Aufgabe
  • firstPrivateContext = für alle Daten von Firebase zu importieren und die Daten an den persistenten Speicher drängen auf Einloggen
  • secondPrivateContext = für die Kontakte aus dem Gerät in Kerndaten bei der Anmeldung zu importieren und Registrieren
  • thirdPrivateContext = für bei der Nutzung der App auf eingehende Daten von Firebase hören

Also das ist, was meine App grob tut. Wenn jemand einen besseren Weg kennt, bin ich offen für irgendwelche Vorschläge.

Dies ist der Code ich benutze, wenn sich der Benutzer anmeldet wieder in:

func importDataFromFirebase(){ 
guard let importContext = importContext else {return} 
FirebaseStore.rootRef.childByAppendingPath("users/"+FirebaseStore.rootRef.authData.uid+"/forums").observeSingleEventOfType(.Value, withBlock:{ 
    snapshot in 
    guard let firebaseData = snapshot.value as? NSDictionary else {return} 
    guard let uids = firebaseData.allKeys as? [String] else {return} 
    importContext.performBlock{ 
     for uid in uids{ 
      guard let forum = NSEntityDescription.insertNewObjectForEntityForName("Forum", inManagedObjectContext: importContext) as? Forum else {return} 
      FirebaseStore.rootRef.childByAppendingPath("forums/"+uid+"/posts").queryOrderedByKey().observeSingleEventOfType(.Value, withBlock: { 
       snapshot in 
          // Saving the chat's messages 
          guard let data = snapshot.value as? NSDictionary else {return} 
          importContext.performBlock{ 
        guard let posts = NSEntityDescription.insertNewObjectForEntityForName("Post", inManagedObjectContext: importContext) as? Post else {return} 
        do{ 
              try importContext.save() 
             }catch let error{ 
         // Error 
             } 
       } 
      }) 
     } 
    } 
}) 
} 

Dieses Diagramm zeigt, was ich versuche zu erreichen: kann

enter image description here

Antwort

1

Sie bauen Ihre Coredata stapeln Sie in irgendeiner Weise, aber zuerst beantworten Sie die Frage - welches Verhalten Sie erreichen möchten. Wenn Sie die Benutzeroberfläche automatisch aktualisieren möchten, wenn etwas importiert wurde, funktioniert Ihre Lösung nicht.

Der ganze Punkt von private managed object context direkt nach persistent store coordinator ist, schweren Betrieb (Speichern in Datei) in der Hintergrundwarteschlange zu halten.

Wenn Sie die Aktualisierungen sofort nach dem Import auf dem Bildschirm anzeigen möchten, sollten Sie den Import unter child private managed object context durchführen, bei dem parentContext auf main managed object context eingestellt ist. Und zum Aktualisieren der Benutzeroberfläche können Sie NSFetchedResultsController verwenden. Auf diese Weise, wann immer Sie in child managed object context speichern - es wird eine Benachrichtigung auslösen, die von NSFetchedResultsController behandelt wird und UI aktualisieren.

Vergessen Sie nicht, den vollen Stapel zu speichern. Es ist nicht genug zu speichern für child managed object context in Datei speichern.

vorschlagen einige Verfahren zum Speichern von vollem Stack zu schreiben, wie diese:

- (void)saveWithCompletionBlock:(void (^)(NSError *error))completionBlock { 

    static dispatch_queue_t queue = NULL; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     queue = dispatch_queue_create("CoreDataSaveQueue", 0); 
    }); 

    //Retain current NSManagedObjectContext to avoid unloading 
    __block NSManagedObjectContext *strongSelf = self; 
    dispatch_async(queue, ^{ 

     __block NSManagedObjectContext *context = strongSelf; 
     __block NSError *error = nil; 

     do { 

      [context performBlockAndWait:^{ 

       if (context != nil && [context hasChanges]) 
        [context save:&error]; 

       context = (nil != error ? nil : context.parentContext); 
      }]; 
     } while (nil != context); 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      if (completionBlock) 
       completionBlock(error); 
     }); 

     //Release current NSManagedObjectContext after save completed 
     strongSelf = nil; 
    }); 
} 

Ich hoffe, meine Erklärung Ihnen helfen zu verstehen, wie Sie Stack aufbauen wollen.

+0

Danke für Ihre Antwort.Das Verhalten, das ich erreichen möchte, besteht darin, zuerst alle Daten aus Firebase zu importieren und sie in den permanenten Speicher zu schieben, wenn sich der Benutzer anmeldet. Dann möchte ich diese Daten anzeigen und die Benutzeroberfläche automatisch aktualisieren, wenn hinzugefügt wird Kerndaten oder Firebase. Ich habe den letzten Teil bereits implementiert, aber ich kämpfe mit dem ersten Teil, manchmal werden alle Daten importiert oder nur halbiert. Mein Import ist überhaupt nicht robust. Ich denke, es hängt auch damit zusammen, wie ich alle meine Core-Daten lösche, wenn sich der Benutzer abmeldet. – C00kieMonsta

+0

Haben Sie herausgefunden, warum nur die Hälfte der Daten importiert wurde? Wie machst du Import? –

+0

Aus Ihrem Code sehe ich, dass Sie keinen Speicherkontext nach 'für uid in uids' aufrufen. Ich bin nicht sehr vertraut mit Firebase, aber soweit ich verstehe diese 'FirebaseStore.rootRef.childByAppendingPath (...' Async-API-Aufruf zum Abrufen von Informationen benötigen Sie tun. Aber Sie nur speichern, nachdem Sie zweite API-Anrufantwort erhalten. Sind Sie sicher, dass Sie 'observeSingleEventOfType' aufrufen sollten? Gibt es den vollständigen Datensatz zurück? –