Warum NSFetchedResultsController ist nicht mit neuen Daten aktualisiert?

Mein Core Data-Modell verfügt über zwei Einheiten: Author und Book mit einem Zu-Viele-Beziehung (one-author->viele Bücher). In der Hauptansicht ich die Anzeige einer Liste von Büchern, in denen jede Zelle enthält buchname und name des Autors. Die Ansicht ist ebenfalls in Abschnitte unterteilt, wobei jeder Abschnitt Titel ist der name des Autors. (beachten Sie, dass "Autor.name" festgelegt ist, für beide sort-descriptor und sectionNameKeyPath)

Hier ist der code (aus Gründen der übersichtlichkeit vereinfacht):

- (NSFetchedResultsController *)fetchedResultsController {

    if (__fetchedResultsController != nil) {
        return __fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"author.name" ascending:YES] autorelease];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"author.name" cacheName:nil] autorelease];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];

    return __fetchedResultsController;
}    

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

     Book* book = [self.fetchedResultsController objectAtIndexPath:indexPath];
     cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", book.name, book.author.name];
    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller {

    [self.tableView reloadData];
}

Nun, wenn der Benutzer ändert den Namen des Autors und geht dann zurück zur Hauptansicht, die Zellen und die Abschnitte zeigen die alten den Namen des Autors. Nach der Suche im Internet fand ich den folgenden code, welche Updates den alten Namen des Autors-Ausgabe in den Zellen, aber nicht im Abschnitt Titel:

- (void)saveAuthorName:(NSString *)newName {
    for (Book* book in author.books) {
        [book willChangeValueForKey:@"author"];
    }

    author.name = newName;

    for (Book* book in author.books) {
        [book didChangeValueForKey:@"author"];
    }

    //save changes
    NSError * error ;
    if( ![self.moc save:&error] ) {
        //Handle error
    } 
}

Warum ist [self.fetchedResultsController sections] enthält noch den alten Namen der Autoren? Bitte um Hilfe!!

Update #1

Dieser Abschnitt bezieht sich auf Antwort #1 von Marcus

Hmmm, immer noch ein wenig verschwommen. Sagen Sie die Anzahl der Abschnitte ist falsch?

Die Anzahl der Abschnitte wurde nicht geändert. Der Inhalt der Objekte in der Sections Eigenschaft array ist falsch.

Basierend auf Ihren code gepostet Sie einfach abrufen die NSManagedObject-Instanzen aus dem NSFetchedResultsController. Vielleicht gibt es einige Verwirrung, was das ist?

In den code, ich bin das abrufen der NSManagedObject Instanzen aus der NSFetchedResultsController um das anzeigen der buchname und name des Autors für jede Zelle in der Tabelle (wenn cellForRowAtIndexPath genannt wird). Allerdings werden die überschriften der einzelnen Abschnitte in UITableView nicht aus NSManagedObject nach meinem Verständnis aber sind genommen aus _NSDefaultSectionInfo Objekt implementiert die NSFetchedResultsSectionInfo Protokoll (wenn titleForHeaderInSection genannt wird).

Erkannte ich, dass dies durch den folgenden code, den ich schrieb für debugging:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    id mySection = [[fetchedBooks sections] objectAtIndex:section];
    NSLog(@"%@", mySection)

    return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
}

Das Ergebnis des log <_NSDefaultSectionInfo: 0x8462b90>.
NSFetchedResultsController Dokumentation für die Abschnitte Eigenschaft zeigt:

/* Returns an array of objects that implement the NSFetchedResultsSectionInfo protocol.
   It's expected that developers use the returned array when implementing the following methods of the UITableViewDataSource protocol

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; 

*/

Also bitte korrigieren Sie mich, wenn ich falsch bin: _NSDefaultSectionInfo ist nicht ein NSManagedObject Recht? Wenn ja, wie kann NSFetchedResultsController Veränderungen erkennen, die für _NSDefaultSectionInfo Objekte beim Autor NSManagedObject geändert werden?

So führt dies zu einer Reihe von Fragen:

Wie ändern Sie den Namen des Autors in dieser anderen Ansicht?

Den code für das ändern der name des Autors bereits oben geschrieben in saveAuthorName. Die Strömung in der App ist wie folgt:

  • Vom main UITableView, die Auswahl der Buch-Zelle, die öffnet neue Buch-Ansicht mit navigation-controller.

  • Aus der Buch-Ansicht, wählen Autor wählen, die öffnet neue Select-Author-Ansicht mit navigation-controller. (alle Autoren sind sich in einem denkmalgeschützten UITableView)

  • Vom Select-Author-Ansicht auswählen aller Autoren, die öffnet neue Bearbeiten-Autor-Ansicht mit navigation-controller.

  • In der Bearbeiten-Autor anzeigen, ändern den Namen des Autors und speichern schließt anzeigen, und bringen Sie die bisherige Ansicht (Wählen-Autor) in Navigations-controller-stack.

  • Es ist nun möglich, wählen Sie verschiedene Autor und Bearbeiten es und so weiter.. bis zum schließen dieser Ansicht. (Bringt Buch-Ansicht)

  • Schließen Buch-Ansicht, bringt für die Haupt-Sicht, in der alle Bücher angezeigt werden.

Ist der name des Autors in der Zelle alt oder nur die Kopfzeile des Abschnitts?

Zelle ist vollkommen aktualisiert mit dem Namen des Autors (vielen Dank an die willChangeValueForKey und didChangeValueForKey genannt in saveAuthorName). Nur Abschnitts-header ist alt.

Was machen deine delegieren Methoden Aussehen?

könnten Sie bitte angeben, welche genau? Ich schrieb alle Delegierten Methoden, die sieht für mich relevant im obigen code-Abschnitt. Dies beinhaltet:

  • cellForRowAtIndexPath

  • titleForHeaderInSection

  • controllerDidChangeContent

Andere Methode erforderlich?

Sind Sie sicher, dass Ihr -[UITableViewDatasource tableView: titleForHeaderInSection:] ist das feuern, nachdem Sie wieder aus dem edit?

100% Prozent sicher. titleForHeaderInSection bringt die alten Werte, und es wird aufgerufen, nachdem die änderungen gespeichert wurden. (cellForRowAtIndexPath ist auch aufgerufen, nachdem die änderungen gespeichert wurden, aber bringt neue Werte)

Was NSFetchedResultsControllerDelegate Methoden sind brennen nach der Rückkehr?

Wenn du meinst, beim speichern (d.h. nach saveAuthorName aufgerufen wird) folgenden Methoden aufgerufen wird:

  • controllerWillChangeContent: (nicht benutzen, nur für debug-info)

  • controller:didChangeObject: (nicht benutzen, nur für debug-info)

  • controllerDidChangeContent:

Wenn du meinst, nach der Rückkehr zur Hauptansicht (bedeutet, dass das schließen der Buch-Ansicht) folgenden Methoden aufgerufen wird:

  • cellForRowAtIndexPath

  • titleForHeaderInSection

  • numberOfSectionsInTableView

  • numberOfRowsInSection

Ich Schätze Ihre Hilfe. Danke!

Update #2

Sind Sie der Umsetzung -controller: didChangeSection: atIndex: forChangeType:?

Ja, das Tue ich aber nicht gefeuert zu werden, wenn Sie ändern Sie den Namen des Autors. Die aktuelle Konfiguration für die NSFetchedResultsController ist wie folgt:

  • Einheit: Buch
  • Sort-Descriptor: der Autor.name
  • sectionNameKeyPath: Autor.name

Ändern ein Buch Namen (anstatt den Namen des Autors) wird Feuer didChangeSection Ereignis, wenn NSFetchedResultsController ist wie folgt konfiguriert:

  • Einheit: Buch
  • Sort-Descriptor: der name
  • sectionNameKeyPath: name

Was bedeutet, dass die Stellvertretung ist richtig süchtig nach den NSFetchedResultsController.

Sieht es als Berufung [book willChangeValueForKey:@"author"] und [book didChangeValueForKey:@"author"] beim ändern der name des Autors ist nicht genug für NSFetchedResultsController um die monitor-Sektion ändert.

InformationsquelleAutor Joshua | 2012-02-25
Schreibe einen Kommentar