Fragen zu Kapitel 7 - Core Data

  • Fragen zu Kapitel 7 - Core Data

    Das Beispiel im Buch verwendet ja einen ArrayController um die Daten im XIB zu managen. Später wird dann zwar eine Data-Source ausprogrammiert, aber die greift letztendlich zur Datenbeschaffung auch wieder auf die XIB-Datei zu. Mir kommt das ein bisschen wie von Hinten durch die Brust ins Auge vor, ist das wirklich eine gängige Methode? (XIB enthält den ArrayController der an den ManagedObjectContext gebunden ist, ein Control (im Beispiel der OutlineView) bekommt seine Daten von einer Data-Source, die aber ihrerseits wieder den ArrayController befragt).

    Mir kommt das ein wenig wie eine Verletzung des MVC-Design Pattern vor, klar der ArrayController ist letztendlich auch ein "Controller". Aber wenn ich zum Beispiel heute ein Programm schreibe mit Speicherung der Daten via Core Data, und in einem Jahr möchte ich das umstellen so dass die Daten per XML-Austausch auf einem Server im Netz gespeichert werden sollen, würde ich bei Einhaltung der MVC Regeln erwarten dass ich für so eine Umstellung den Interface Builder nicht mehr starten muss - das wäre aber im beschriebenen Fall nicht gegeben.

    Sauberer fände ich es also, wenn die anzuzeigenden Daten im Window- bzw. ViewController als Attribut gespeichert sind, oder per Data-Source (die vielleicht noch ausgelagert in eine eigene Klasse) zur Verfügung stehen. Dann könnte man im IB die entsprechende Anbindung machen, und wo die Daten herkommen ist dem View vollkommen egal.

    Was für Möglichkeiten würde es denn geben den IB bei einer Data-Source für einen Outline-View aus der Datenbeschaffung ganz rauszuhalten? Einen NSArrayController programmatisch basteln und binden? Keinen ArrayController zu verwenden und alles per FetchRequest beschaffen? Oder wäre so eine Trennung eher unüblich und bringt zu viele Probleme mit sich?
  • Ein Verstoß gegen das MVC-Pattern ist das nicht, weil Array-Controller und Data-Source-Implementierung beide auf der Controllerebene liegen. Deshalb sind sie auch beide im Kapitel 7 besprochen. :) Der Hintergrund ist aber, wie im Buch erläutert, dass ich nicht alles neu programmieren will.

    Du musst auch für eine Umstellung von Core Data auf XML nicht das UI ändern. Da der Controller im Xib liegt, musst du das Xib ändern. Um also dieses Unbehagen zu beseitigen, müsstest du den Array-Controller aus dem Xib entfernen. Das kannst du machen. Es ist aber üblich, den Controller im Xib zu haben. Denke etwa nur an das App-Delegate. Das liegt auch im Xib.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    ...weil Array-Controller und Data-Source-Implementierung beide auf der Controllerebene liegen
    Wie gesagt, ist schon klar dass der ArrayController auch ein Controller ist, es kam mir nur komisch vor dass er im NIB deklariert wird. Das NIB ist zwar wohl schon noch etwas mehr als nur die UI, ich bin es nur aus anderen Sprachen/Umgebungen gewöhnt dass hier wesentlich strenger getrennt wird.

    Amin Negm-Awad schrieb:

    Es ist aber üblich, den Controller im Xib zu haben
    Das ist der Punkt auf den ich hinaus wollte ;) Wenn es üblich ist, dann mache ich es auch erstmal so. Will mir nicht gleich mein erstes echtes Projekt mit Frickeleien unnötig schwer machen. Für ein größeres Vorhaben welches aber noch nicht akut ist, werde ich mir dann aber nochmals die Alternativen anschauen.
  • LbbnPx schrieb:

    Amin Negm-Awad schrieb:

    ...weil Array-Controller und Data-Source-Implementierung beide auf der Controllerebene liegen
    Wie gesagt, ist schon klar dass der ArrayController auch ein Controller ist, es kam mir nur komisch vor dass er im NIB deklariert wird. Das NIB ist zwar wohl schon noch etwas mehr als nur die UI, ich bin es nur aus anderen Sprachen/Umgebungen gewöhnt dass hier wesentlich strenger getrennt wird.

    Der Controller wird im Xib instantiiert.

    Das hat auch nichts mit Strenge zu tun. Es hat einfach etwas mit der Definition zu tun, wozu ein Nib da ist. Du kämst ja auch nicht auf den Gedanken zu sagen, dass Sourcen für Controllerimplementierungen da sind. Und wie gesagt: Du verwendest ständig Controller im Xib.

    LbbnPx schrieb:

    Amin Negm-Awad schrieb:

    Es ist aber üblich, den Controller im Xib zu haben
    Das ist der Punkt auf den ich hinaus wollte ;) Wenn es üblich ist, dann mache ich es auch erstmal so. Will mir nicht gleich mein erstes echtes Projekt mit Frickeleien unnötig schwer machen. Für ein größeres Vorhaben welches aber noch nicht akut ist, werde ich mir dann aber nochmals die Alternativen anschauen.

    Die Alternativen zu Controllern im Xib? Die nennt sich: Viel Code.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Die Alternativen zu Controllern im Xib? Die nennt sich: Viel Code.

    Naja, das habe ich mir fast gedacht ... aber ich werde, wenn es dann soweit ist, halt abwägen müssen was wichtiger ist ...

    Ich habe in der Zwischenzeit auch weiter mit Core Data geübt, habe jetzt aber noch ein Problem, das ich irgendwie nicht in den Griff bekomme. Ich habe einen Outlineview, bei dem die Objekte in sich selbst verschoben werden können (beliebige Verschachtelung). Das Verschieben passiert per Drag and Drop, letztendlich mache ich die Zuordnung wie folgt:

    Quellcode

    1. - (BOOL)outlineView:(NSOutlineView*)outlineView
    2. acceptDrop:(id<NSDraggingInfo>)info
    3. item:(id)item
    4. childIndex:(NSInteger)index
    5. {
    6. … // gekürzt
    7. for (id itemURL in itemURLs) {
    8. objectID = [coordinator managedObjectIDForURIRepresentation:itemURL];
    9. itemToMove = [context objectWithID:objectID];
    10. // ItemToMove enthält zu verschiebenden Eintrag
    11. // item ist das Ziel (Gruppe)
    12. [itemToMove setValue:item forKey:@"parentEntry"];
    13. }
    14. [documentWC.sidebarView reloadData];
    15. return YES;
    16. }
    Alles anzeigen


    Anschließend wird der OutlineView neu aufgebaut. Auf der obersten Ebene möchte ich alle Einträge ausgeben, die keinen übergeordneten Eintrag haben, das Feld "parentEntry" also leer ist:

    Quellcode

    1. - (NSInteger) outlineView:(NSOutlineView*)outlineView
    2. numberOfChildrenOfItem:(id)item
    3. {
    4. // Wurzelelement
    5. if (!item) {
    6. // Alle listEntries ohne Gruppe
    7. NSPredicate *topEntry = [NSPredicate predicateWithFormat:@"parentEntry = NULL"];
    8. [listEntryController setFilterPredicate:topEntry];
    9. int count = [[listEntryController arrangedObjects] count];
    10. NSLog(@"ChildsOfItem: %@", item);
    11. NSLog(@"Count: %i", count);
    12. return count;
    13. } else {
    14. … // gekürzt
    15. }
    Alles anzeigen

    Problem: Sobald ich ein Eintrag aus der obersten Ebene verschiebe und in outlineView:acceptDrop... zuordne, liefert die anschließende outlineView:numberOfChildrenOfItem den falschen Wert, die Abfrage scheint noch nicht zu erkennen dass sich etwas geändert hat. Sobald ich einmal speichere und die Datei neu lade liefert die Methode wieder den richtigen Wert. Wie kann ich denn nun in outlineView:acceptDrop sagen dass die Änderungen tatsächlich und verbindlich ausgeführt werden sollen, so dass nachfolgende Methoden auf den richtigen Datenstand zugreifen?

    P.S. Fand das Buch auch Klasse, hat mir viel gebracht. Habe gerade auch den Band 2 bestellt - muss auch noch was übers Drucken lernen ...
  • Zu Xibs: Wenn du meinst, Cocoa besser programmieren zu können, als es ist, solltest du dich auf einsame Abende vorbereiten. Ich weiß aber auch nicht, woher deine Meinung stammt, im Xib dürften sich keine Controller befinden!?

    Zum anderen: Stell das mal ins normale Forum. Das hat ja nichts mit dem Buch zu tun und dort wirst du mehr Leser finden.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Zu Xibs: Wenn du meinst, Cocoa besser programmieren zu können, als es ist, solltest du dich auf einsame Abende vorbereiten. Ich weiß aber auch nicht, woher deine Meinung stammt, im Xib dürften sich keine Controller befinden!?

    Zum Hintergrund: Ich möchte (zu gegebener Zeit) ein Programm schreiben welches es in zwei Varianten geben soll. Variante 1) soll als Einzelplatzversion ohne Installationsaufwand mit lokaler Datenhaltung funktionieren, Variante 2) soll als Mehrplatzversion die Daten auf einem Server halten, und die Clients holen sich die Daten von dort. Mein Gedanke war daher dass ich die komplette Datenbeschaffung soweit wie möglich in eine Klasse kapseln möchte, so dass es der XIB-Datei vollkommen egal ist woher die Daten kommen. Dann müsste ich nur diese eine Klasse ändern und hätte eine andere Datenablage, ohne den Rest vom Programm anpassen zu müssen.

    Wie gesagt, das war der ursprüngliche Gedanke. Nach den gewonnenen Kenntnissen wäre es wahrscheinlich sinnvoller für den Anwendungszweck komplett auf Core-Data zu verzichten, und dem Programm in der Einzelplatzversion einen lokalen Server mitzugeben, so dass das Programm immer gleich läuft. Falls es PostgreSQL als Datenbank wird (derzeit mein Favorit) müsste ich dann aber die Datenbank als ausführbare Datei in mein Bundle verpacken und aus der App heraus automatisch im Hintergrund starten (es soll kein Installationsaufwand für den Anwender entstehen), dass ist dann auch nicht ganz so trivial. Deswegen wäge ich momentan einfach alle Möglichkeiten gegeneinander ab. Aber das steht auch noch in etwas fernerer Zukunft, fürs erste werde ich meine Zeit einigen einfacheren Projekten widmen.

    Zum anderen Thema: Ich wollte wegen der Frage keine neuen Thread aufmachen, aber das werde ich dann doch mal tun ...
  • Wahrscheinlich ist heute die Uhrzeit besser, nochmal kurz in den Code geschaut, eine kleine Änderung gemacht, und mein Problem ist gelöst. Habe einfach noch ein rearrangeObjects an den ArrayController geschickt:

    ...
    [listEntryController rearrangeObjects];
    [documentWC.sidebarView reloadData];
    return YES;
    }
  • LbbnPx schrieb:

    Amin Negm-Awad schrieb:

    Zu Xibs: Wenn du meinst, Cocoa besser programmieren zu können, als es ist, solltest du dich auf einsame Abende vorbereiten. Ich weiß aber auch nicht, woher deine Meinung stammt, im Xib dürften sich keine Controller befinden!?

    Zum Hintergrund: Ich möchte (zu gegebener Zeit) ein Programm schreiben welches es in zwei Varianten geben soll. Variante 1) soll als Einzelplatzversion ohne Installationsaufwand mit lokaler Datenhaltung funktionieren, Variante 2) soll als Mehrplatzversion die Daten auf einem Server halten, und die Clients holen sich die Daten von dort. Mein Gedanke war daher dass ich die komplette Datenbeschaffung soweit wie möglich in eine Klasse kapseln möchte, so dass es der XIB-Datei vollkommen egal ist woher die Daten kommen. Dann müsste ich nur diese eine Klasse ändern und hätte eine andere Datenablage, ohne den Rest vom Programm anpassen zu müssen.

    Das geht ohne Weiteres auch dann, wenn die Klasse in einem Xib instantiert wird. Du musst dazu nur die Erzeugung der Instanz überschreiben und verschiedene Subklassen liefern. Nennt sich Class-Cluster.

    LbbnPx schrieb:

    Wie gesagt, das war der ursprüngliche Gedanke. Nach den gewonnenen Kenntnissen wäre es wahrscheinlich sinnvoller für den Anwendungszweck komplett auf Core-Data zu verzichten, und dem Programm in der Einzelplatzversion einen lokalen Server mitzugeben, so dass das Programm immer gleich läuft. Falls es PostgreSQL als Datenbank wird (derzeit mein Favorit) müsste ich dann aber die Datenbank als ausführbare Datei in mein Bundle verpacken und aus der App heraus automatisch im Hintergrund starten (es soll kein Installationsaufwand für den Anwender entstehen), dass ist dann auch nicht ganz so trivial. Deswegen wäge ich momentan einfach alle Möglichkeiten gegeneinander ab. Aber das steht auch noch in etwas fernerer Zukunft, fürs erste werde ich meine Zeit einigen einfacheren Projekten widmen.

    Zum anderen Thema: Ich wollte wegen der Frage keine neuen Thread aufmachen, aber das werde ich dann doch mal tun ...

    Core Data ist keine Datenbank. Es speichert den Graphen in einem Dokument. Dokumente und Netzwerk vertragen sich nur schlecht.

    Mail mal die Leute von Project Wizard an. Die haben schon immer ein Framework gebaut, welches einen Netzwerkzugrifflayer darüber legt.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?