2012-06-09 23 views
13

Tengo una UITableView poblada con un NSFetchedResultsController estándar. Sin embargo, me gustaría añadir una fila o una sección (preferiblemente una fila, pero cualquiera funcionaría realmente bien)NSFetchedResultsController antepone una fila o sección

La única forma en que puedo ver hacer esto ahora es reescribiendo todos los NSIndexPath manualmente cuando se trata de la sección/rows que maneja los datos de NSFetchedResultsController para engañarlo al ver la sección en el índice 0 y comenzar con la fila en el índice 0. Esto sin embargo parece ser una muy mala idea que rápidamente se volvería confusa, por lo que preferiría evitar eso.

Un buen ejemplo de esto sería en la aplicación oficial de Twitter cuando lo inicies por primera vez y te guío para agregar algunas personas de tu lista de amigos.

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

La sección roja es más o menos lo que me gustaría lograr, y la sección amarilla que supongo que es el resultado de una NSFetchedResultsController en la misma sección (aunque con su estilo a medida que podría ser una separada sección).

+0

posible duplicado de [Insertar filas adicionales a un UITableView gestionado por NSFetchedResultsController] (http://stackoverflow.com/questions/ 9604410/add-extra-row-to-a-uitableview-managed-by-nsfetchedresultscontroller) – JosephH

Respuesta

31

Esto es posible de hacer de una manera bastante limpia.

Supongo que está comenzando con una tabla de configuración estándar configurada con un estándar NSFetchResultsController que usa el código de muestra de Apple.

Lo primero que necesita dos funciones de utilidad:

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

Estos deben ser bastante explica por sí mismo - sólo son ayudantes para hacer frente a la adición de la fila adicional cuando queremos utilizar una ruta de índice entre los controladores resultados inverosímiles para acceder a la mesa, o eliminarla cuando va por el otro camino.

entonces tenemos que crear la célula extra:

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

asegurarse configuramos correctamente (configurecell es llamado solo para las células procedentes del controlador de extraer resultados):

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

y di la tabla vista existe:

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

y responden a la selección:

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

y luego volver a asignar las actualizaciones que recibimos desde el controlador resultados:

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

Si en este enfoque, me gusta eliminar dinámicamente la primera fila, será posible. – cocoaNoob

+0

@cocoaNoob Sí, eso funcionaría bien. Mientras mapee indexPath correctamente, puede hacer prácticamente cualquier cosa. – JosephH

+0

Sí, lo intenté en lugar de usar 1, estoy usando la variable de instancia. Un enfoque muy bueno y claro. Gracias por compartir su solución @JosepH. – cocoaNoob

3

Entiendo su preocupación sobre la complejidad, pero en realidad solo agrega 1 a numberOfRowsInSection: y agrega 1 a indexPath.row en cellForRowAtIndexPath: (además de agregar el código para la fila 0).

Otra solución no tendría que ser muy elaborada para ser aún más engorrosa.

Dicho esto, realmente parece que el "encabezado" que está proponiendo es un candidato típico para un encabezado de sección .

+0

Ese es un punto justo, básicamente solo estaba comprobando si no había algún método que no supiera sobre NSFetchedResultsController que permitiera preceder o añada un conjunto de filas a los resultados que devuelve para que pueda personalizarlos. –

Cuestiones relacionadas