NSFetchtedResultsController und sections bei many-to-many Relationships

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSFetchtedResultsController und sections bei many-to-many Relationships

    Ich habe zwei Entitäten die jeweils eine many-to-many-Relationships aufeinander haben, also

    Warengruppen <<--->> Artikel

    Ich möchte eine UITableView haben, die z.B. so aussieht:


    Warengruppe 1
    -> Artikel A
    -> Artikel B
    -> Artikel C

    Warengruppe 2
    -> Artikel A
    -> Artikel D
    -> Artikel F

    Warengruppe 3
    -> Artikel B
    -> Artikel C
    -> Artikel G

    usw.

    Bei einer 1:n-Beziehung (also Warengruppen <--->> Artikel), würde der folgende FetchRequest funktionieren.

    Quellcode

    1. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    2. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artikel" inManagedObjectContext:self.managedObjectContext];
    3. [fetchRequest setEntity:entity];
    4. [fetchRequest setFetchBatchSize:20];
    5. NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"artikelInGruppe.name" ascending:YES];
    6. NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    7. NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, sortDescriptor2, nil];
    8. [fetchRequest setSortDescriptors:sortDescriptors];
    9. NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"artikelInGruppe.name" cacheName:@"Master"];
    10. aFetchedResultsController.delegate = self;
    11. self.fetchedResultsController = aFetchedResultsController;
    12. NSError *error = nil;
    13. if (![self.fetchedResultsController performFetch:&error]) {
    14. NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    15. abort();
    16. }
    17. return __fetchedResultsController;
    Alles anzeigen


    Das Ergebnis sähe dann z.B. so aus:

    Warengruppe 1
    -> Artikel A
    -> Artikel B

    Warengruppe 2
    -> Artikel C
    -> Artikel D

    usw.




    Bei der n:m-Beziehung gibt es natürlich eine Exception: "Invalid to many relationship in setPropertiesToFetch" - was auch klar ist, da für eine Section in diesem Fall ein NSSet geliefert wird.

    Ich könnte natürlich einen Request über die Warengruppen machen und dann die einzelnen Artikel jeweils herausfiltern usw.
    Ich frage mich aber, ob es nicht eine Möglichkeit gibt, das direkt in dem NSFetchResultsController komplett anzufackeln (über ein Predicate?)?
    Was ich im Netz dazu gefunden habe, hat mich bislang nicht weiter gebracht. Ist es also möglich und wenn ja wie?
  • Ich würde als Basis der TableView-Daten die Warengruppen nehmen.

    Wenn Du in die Warengruppe ein Property oder eine Methode einbaust, die die Anzahl seiner Artikel zurückgibt, kannst Du die Fragen des TableViews nach Anzahl der Zellen, Cell usw. relativ einfach beantworten, weil deine TableView-Methoden im Prinzip nach der Struktur Deines Datenmodells aufgebaut wären.

    No.
  • Ja, das meinte ich mit "ich könnte natürlich einen Request über die Warengruppen machen und dann die einzelnen Artikel jeweils herausfiltern usw." Da ist dann eben etwas handarbeit gefragt.


    Worum es mir geht, ist die Frage, ob der FRC auch im Falle einer many-to-many Relationship die 'ganze Arbeit' übernehmen kann.
    Wie oben beispielhaft aufgezeigt, ist das ja bei einer 1:n-Beziehung kein Problem: Der FRC sorgt für alles, für die Sections, die Sortierung der Sections, die Items in den einzelnen Sektionen und dessen Sortierung usw.

    Bei der n:m-Beziehung tritt beim FRC das Problem auf, dass man auf eine to-many-Relationship zurückgreift, entweder bei einem SortDescriptor oder bei "sectionNameKeyPath:".
    Wenn man diese to-many-Relationship für den FRC auflösen könnte, könnte er wieder die ganze Arbeit übernehmen. Und die Frage ist, ob das geht.