2012-06-09 8 views
13

Ich habe eine UITableView mit einem Standard NSFetchedResultsController aufgefüllt. Allerdings würde ich gerne eine Reihe oder einen Abschnitt vorziehen (Zeile vorzugsweise, aber beides würde wirklich gut funktionieren.)NSFetchedResultsController eine Zeile oder einen Abschnitt voranstellen

Die einzige Möglichkeit, die ich sehen kann, dies jetzt zu tun, ist, alle NSIndexPaths manuell umschreiben, wenn Sie mit dem Abschnitt befassen/rows, die sich mit den Daten von NSFetchedResultsController beschäftigen, um sie dazu zu bringen, Abschnitt bei Index 0 zu sehen und mit Zeile bei Index 0 zu beginnen. Dies scheint jedoch eine wirklich schlechte Idee zu sein, die schnell verwirrend werden würde.

Ein gutes Beispiel dafür wäre in der offiziellen Twitter App, wenn Sie es zum ersten Mal starten und ich führe Sie durch Hinzufügen von einigen Personen aus Ihrer Freundesliste.

Screenshot of Twitter app's suggestions page, with the relevant sections highlighted

Der rote Abschnitt ist ziemlich viel, was ich erreichen möchte, und der gelbe Abschnitt Ich gehe davon aus, die Ergebnisse aus einem NSFetchedResultsController im selben Abschnitt (wenn auch mit ihrer Gewohnheit Styling es ein separates sein könnte Abschnitt.)

+0

möglich Duplikat [Hinzufügen zusätzliche Zeile zu einem UITableView von NSFetchedResultsController verwaltet] (http://stackoverflow.com/questions/ 9604410/add-extra-row-zu-a-uitableview-managed-by-nsfetchedresultscontroller) – JosephH

Antwort

31

Dies ist auf ziemlich saubere Weise möglich.

Ich gehe davon aus, dass Sie mit einer Standardtabellenansicht beginnen, die mit einem Standard-NSFetchResultsController eingerichtet wurde, der den Beispielcode von Apple verwendet.

Zuerst müssen Sie zwei Hilfsfunktionen:

- (NSIndexPath *)mapIndexPathFromFetchResultsController:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == 0) 
     indexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]; 

    return indexPath; 
} 

- (NSIndexPath *)mapIndexPathToFetchResultsController:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == 0) 
     indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]; 

    return indexPath; 
} 

Diese sollten ziemlich selbsterklärend sein - sie sind nur Helfer mit Hinzufügen der Extrareihe beschäftigen, wenn wir einen Index Pfad von den abgerufenen Ergebnisse Controller verwenden möchten auf den Tisch zugreifen oder ihn entfernen, wenn er in die andere Richtung geht.

Dann brauchen wir die zusätzliche Zelle zu erstellen:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"MyCellId"; 

    if (indexPath.section == 0 && indexPath.row == 0) 
    { 
     UITableViewCell *cell; 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 
     cell.selectionStyle = UITableViewCellSelectionStyleGray; 
     cell.textLabel.text = NSLocalizedString(@"Extra cell text", nil); 

     return cell; 
    } 

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

    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

sicherstellen, dass wir es richtig konfigurieren (configurecell nur für Zellen von der Steuerung holen Ergebnisse genannt werden):

// the indexPath parameter here is the one for the table; ie. it's offset from the fetched result controller's indexes 
- (void)configureCell:(SyncListViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 
    indexPath = [self mapIndexPathToFetchResultsController:indexPath]; 

    id *obj = [fetchedResultsController objectAtIndexPath:indexPath]; 
    <... perform normal cell setup ...> 
} 

und sagen die Tabellenansicht es existiert:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    NSInteger numberOfRows = 0; 

    if ([[fetchedResultsController sections] count] > 0) { 
     id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; 
     numberOfRows = [sectionInfo numberOfObjects]; 
    } 

    if (section == 0) 
     numberOfRows++; 

    return numberOfRows; 
} 

und antworten auf Auswahl:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 

    if (indexPath.section == 0 && indexPath.row == 0) 
    { 
     [self doExtraAction]; 
     return; 
    } 

    ... deal with selection for other cells ... 

und dann alle Updates neu zuordnen wir aus den Ergebnissen Controller erhalten:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
    UITableView *tableView = self.tableView; 

    indexPath = [self mapIndexPathFromFetchResultsController:indexPath]; 
    newIndexPath = [self mapIndexPathFromFetchResultsController:newIndexPath]; 

    switch(type) { 
     ... handle as normal ... 
+0

Wenn ich in diesem Ansatz die erste Zeile dynamisch löschen möchte, ist es möglich. – cocoaNoob

+0

@cocoaNoob Ja, das würde gut funktionieren. Solange Sie den IndexPath korrekt zuordnen, können Sie im Wesentlichen alles tun. – JosephH

+0

Ja, ich habe es versucht, anstatt 1 zu verwenden, verwende ich Instanzvariable. Ein sehr guter und klarer Ansatz. Danke, dass Sie Ihre Lösung @JosepH teilen. – cocoaNoob

3

ich verstehe Ihre Bedenken hinsichtlich der Komplexität, aber es ist wirklich nur das Hinzufügen 1-numberOfRowsInSection: und das Hinzufügen von 1-indexPath.row in cellForRowAtIndexPath: (neben nehmen sie den Code für Zeile 0).

Eine andere Lösung müsste nicht sehr aufwändig sein, um noch mühsamer zu werden.

Das heißt, es scheint wirklich, dass die "Überschrift", die Sie vorschlagen, ein typischer Kandidat für eine Abschnitt Header ist.

+0

Das ist ein guter Punkt, ich habe meistens nur überprüft, ob es eine Methode gab, die ich nicht über NSFetchedResultsController kannte oder fügen Sie eine Reihe von Zeilen an die zurückgegebenen Ergebnisse an, damit Sie sie anpassen können. –

Verwandte Themen