2009-10-31 13 views

Respuesta

135

proporcionar su propia caracteres índice:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    return[NSArray arrayWithObjects:@"a", @"e", @"i", @"m", @"p", nil]; 
} 

y luego:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString 
    *)title atIndex:(NSInteger)index { 
     return <yourSectionIndexForTheSectionForSectionIndexTitle >; 
} 

Usted necesitará secciones.

+21

¿Hay alguna manera de tener índices sin tener secciones (para una lista plana)? –

+12

@ThEuSeFuL Puede tener secciones sin mostrar encabezados de sección. Esto se vería como una lista plana para el usuario final. –

+10

¿Qué significa "yourSectionIndexForTheSectionForSectionIndexTitle"? – ravoorinandan

2

implementar los métodos de delegado -sectionIndexTitlesForTableView: y -tableView:sectionForSectionIndexTitle:atIndex:

consulte la documentación UITableViewDataSource para obtener más información.

0

Si está utilizando MonoTouch, anule el método SectionIndexTitles (UITableView) en la clase UITableViewDataSource. Simplemente devuelve una serie de cadenas y la subclase se ocupa del resto.

class TableViewDataSource : UITableViewDataSource 
{ 
    public override string[] SectionIndexTitles(UITableView tableView) 
    { 
    return new string[] { /*your string values */}; 
    } 
} 

* solo una pista para aquellos de nosotros que usen C# y Mono (.NET) para escribir aplicaciones de iPhone. :)

21

Un grupo de personas preguntó si era posible hacerlo sin secciones. Quería lo mismo y encontré una solución que podría ser un poco turbia y no devuelve ningún valor a sectionForSectionIndexTitle, pero si se encuentra en una esquina y no quiere tener que hacer una sección para cada letra del alfabeto, esto es una solución segura Perdón por cualquier código Nazis por adelantado. : P

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    if (thisTableDataIsShowing) 
    { 
     NSMutableArray *charactersForSort = [[NSMutableArray alloc] init]; 
     for (NSDictionary *item in d_itemsInTable) 
     { 
      if (![charactersForSort containsObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]]) 
      { 
       [charactersForSort addObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]]; 
      } 
     } 
     return charactersForSort; 
    } 
    return nil; 
} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { 
    BOOL found = NO; 
    NSInteger b = 0; 
    for (NSDictionary *item in d_itemsInTable) 
    { 
     if ([[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1] isEqualToString:title]) 
      if (!found) 
      { 
       [d_yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:b inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
       found = YES; 
      } 
     b++; 
    } 
} 

Funciona muy bien si está obteniendo una gran cantidad de datos y seccionando que tomaría un montón de trabajo. :) Intenté usar variables genéricas para que supiera lo que estaba haciendo. d_itemsInTable es un NSArray de NSDictionaries que estoy enumerando en UITableView.

+1

Puede simplemente devolver b. – AMayes

+1

Fax divertido: si devuelve -1, ignorará las advertencias del compilador, y no intentará desplazarse a esa sección desde el método secciónForSectionIndexTitle – elimirks

+0

Una muestra realmente impresionante gracias a que se puede agregar un freno después del fondo = SÍ; tampoco sería tan malo ^^ – Mingebag

35

Algo más que debe tener en cuenta es localizar las secciones para cada idioma. Después de cavar un poco, me encontré con UILocalizedIndexedCollation a ser bastante útil:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section]; 
} 

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]; 
} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { 
    return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index]; 
} 

https://developer.apple.com/documentation/uikit/uilocalizedindexedcollation

+0

+1 manera fácil y agradable para IndexSction – iMeMyself

33

me ocurrió con un enfoque alternativo para el manejo de una lista única letra del alfabeto sin usar secciones. Es similar a la respuesta de Zaph, pero en lugar de obtener ningún valor al devolver un nuevo índice (ya que siempre tendremos 1 sección), calculamos el índice para la ubicación del primer elemento en la matriz que comienza con un cierto carácter, luego desplazamos lo.

La desventaja es que esto requiere buscar en la matriz cada vez (¿es esto absolutamente terrible?), Sin embargo, no noté ningún retraso o comportamiento lento en el simulador de iOS o en mi iPhone 4S.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    return[NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil]; 
} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { 

    NSInteger newRow = [self indexForFirstChar:title inArray:self.yourStringArray]; 
    NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; 
    [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO]; 

    return index; 
} 

// Return the index for the location of the first item in an array that begins with a certain character 
- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array 
{ 
    NSUInteger count = 0; 
    for (NSString *str in array) { 
    if ([str hasPrefix:character]) { 
     return count; 
    } 
    count++; 
    } 
    return 0; 
} 

adición de propiedad para almacenar última seleccionados índice como

@property (assign, nonatomic) NSInteger previousSearchIndex; 

y almacenar esta propiedad cada momento como:

- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array 
{ 
    NSUInteger count = 0; 
    for (NSString *str in array) { 
     if ([str hasPrefix:character]) { 
      self.previousSearchIndex = count; 
      return count; 
     } 
     count++; 
    } 
    return self.previousSearchIndex; 
} 

y actualizar scrollToRow código como:

[tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

Haga este método aún mejor y con buena animación.

+14

upvoted solo porque significa que no tuve que escribir en la matriz del alfabeto! –

+1

heh. Tampoco es una mala solución ... apple me aceptó para cocoa camp usando esto en mi código de muestra. si eso significa que oficialmente lo endosan o no ... No lo sé;). –

+0

@PaulCezanne En realidad, para hacerlo más limpio le sugiero que recorra su conjunto de cadenas y tome las primeras letras mayúsculas de todas las cadenas para que su lista sea dinámica, ya que no tendrá ninguna Q si no tiene ningún elemento que comienzan con la letra Q. Avíseme si desea que actualice mi código para mostrar esto. –

3

Aquí es una versión modificada de la función de Kyle que maneja el caso de hacer clic en un índice para el que no tiene una cadena:

- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array 
{ 
    char testChar = [character characterAtIndex:0]; 
    __block int retIdx = 0; 
    __block int lastIdx = 0; 

    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     char firstChar = [obj characterAtIndex:0]; 

     if (testChar == firstChar) { 
      retIdx = idx; 
      *stop = YES; 
     } 

     //if we overshot the target, just use whatever previous one was 
     if (testChar < firstChar) { 
      retIdx = lastIdx; 
      *stop = YES; 
     } 

     lastIdx = idx; 
    }]; 
    return retIdx; 
} 
3

Si estás utilizando un NSFetchedResultsController, sólo puede hacer:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    return [frc sectionIndexTitles]; 
} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { 
    return [frc sectionForSectionIndexTitle:title atIndex:index]; 
} 
2

Aquí hay una solución simple en Swift, suponiendo que tiene los encabezados de título en una matriz. Si no se pudo encontrar el título, devolverá el índice anterior en la matriz.

func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? { 
    return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.flatMap{String($0)} 
} 

func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int { 
    return self.headerTitles.filter{$0 <= title}.count - 1 
} 
+0

Creo que es preferible cambiar la segunda línea de retorno a 'return self.headerTitles.count - self.headerTitles.filter {$ 0> title} .count' para devolver el índice de la primera sección en vez de la última coincidencia para el título del índice dado –

+0

Depende de lo que el cliente espera, en realidad. Es probable que la funcionalidad que elijas sea la opuesta a la que desean. :) – Samah

Cuestiones relacionadas