2012-06-09 13 views
13

Mam UITableView zapełniony standardowym NSFetchedResultsController. Chciałbym jednak wstawić wiersz lub sekcję (najlepiej wiersz, ale każdy z nich działałby naprawdę dobrze).NSFetchedResultsController poprzedzający wiersz lub sekcję

Jedyny sposób, jaki mogę teraz zobaczyć, to przepisanie wszystkich NSIndexPath ręcznie podczas pracy z sekcją/wiersze zajmujące się danymi z NSFetchedResultsController, aby oszukać w sekcji o indeksie 0 i zaczynając od rzędu na indeksie 0. To jednak wydaje się bardzo złym pomysłem, który szybko stałby się mylący, więc wolałbym tego uniknąć.

Dobrym tego przykładem może być oficjalna aplikacja Twitter po uruchomieniu komputera po raz pierwszy i przeprowadzam Cię przez proces dodawania osób z listy znajomych.

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

Czerwona sekcja jest dość dużo, co chciałbym osiągnąć, a żółta sekcja zakładam to wyniki z NSFetchedResultsController w tej samej sekcji (choć ze swoim niestandardowym stylizacji może być oddzielnym sekcja.)

+0

możliwe duplikat [Dodaj dodatkowy wiersz UITableView zarządzanego przez NSFetchedResultsController] (http://stackoverflow.com/questions/ 9604410/add-extra-row-to-a-uitableview-managed-by-nsfetchedresultscontroller) – JosephH

Odpowiedz

31

Można to zrobić w dość czysty sposób.

Zakładam, że zaczynasz od standardowej konfiguracji tableview ze standardowym NSFetchResultsController, który używa przykładowego kodu Apple.

Najpierw trzeba dwie funkcje użytkowe:

- (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; 
} 

Powinny być dość oczywista - one po prostu do czynienia z pomocników dodając dodatkowy wiersz, gdy chcemy wykorzystać ścieżkę indeksu z wyników idących kontrolerów aby uzyskać dostęp do stołu lub usunąć go podczas przechodzenia w drugą stronę.

Następnie musimy stworzyć dodatkową komórkę:

- (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; 
} 

upewnić się, że go skonfigurować poprawnie (configurecell zostanie wywołana tylko dla komórek z kontrolerem pobrać wyników):

// 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 ...> 
} 

i powiedzieć tableview istnieje:

- (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; 
} 

i odpowiedzi na wybór:

- (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 ... 

a następnie przemapować żadnych nowości, jakie otrzymujemy od kontrolera wyniki:

- (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

Jeśli w tym podejściu lubię dynamicznie usuwać pierwszy wiersz, będzie to możliwe. – cocoaNoob

+0

@ cocoaNoob Tak, to działa dobrze. Dopóki poprawnie mapujesz indeks IndexPath, możesz zrobić zasadniczo wszystko. – JosephH

+0

Tak, próbowałem zamiast używać 1, używam zmiennej instancji. Bardzo dobre i jasne podejście. Dziękujemy za udostępnienie rozwiązania @JosepH. – cocoaNoob

3

Rozumiem twoje obawy dotyczące złożoności, ale tak naprawdę po prostu dodawanie 1 do numberOfRowsInSection: i dodawanie 1 do indexPath.row w cellForRowAtIndexPath: (oprócz dodawania kodu dla wiersza 0).

Inne rozwiązanie nie musi być bardzo skomplikowane, aby stać się jeszcze bardziej kłopotliwe.

W związku z tym wydaje się, że "nagłówek", który proponujesz, jest typowym kandydatem do nagłówka nagłówka.

+0

To prawda, głównie sprawdzałem, czy nie było jakiejś metody, o której nie wiedziałem w NSFetchedResultsController, która pozwoliła ci zacząć lub dołącz zestaw wierszy do wyników, które zwraca, abyś mógł je dostosować. –

Powiązane problemy