从 NSArray 为 UITableView 创建索引

Posted

技术标签:

【中文标题】从 NSArray 为 UITableView 创建索引【英文标题】:Create index for UITableView from an NSArray 【发布时间】:2011-08-23 09:23:09 【问题描述】:

我读过创建索引(uitableview 旁边的 a-z)的最佳方法是设置一个 nsdictionaries 数组,其中每个字典对应一个部分,并且 rowValue 键包含一个数组行。

NSDictionary
    headerTitle => ‘A’
    rowValues => ”Aardvark”, “Ape”, “Aquaman”
NSDictionary
    headerTitle => ‘B’
    rowValues => ”Bat”, “Boot”, “Bubbles” etc

但是如何从所有行标题的数组中创建它 - ”Aardvark”、“Ape”、“Aquaman”、“Bat”、“Boot”、“Bubbles”、“Cat”、“Cabbage”等等 ...?

【问题讨论】:

【参考方案1】:

我最近有一个类似的目标,这就是我解决它的方法。与 Robin 的解决方案相比,它的优势在于它会根据数组的内容动态创建索引标题数组,并且不会包含空白部分的索引(而且它更简洁一些)。

我创建了一个NSMutableDictionary 类别,它接受一个数据数组作为参数并返回一个NSMutableDictionary(我们称之为indexDictionary,它应该是一个实例变量):

// if your data is static, you can call this in `viewDidLoad`
indexDictionary = [NSMutableDictionary createDictionaryForSectionIndex:arrayOfStrings];

分类方法:

@implementation NSMutableDictionary (DictionaryForSectionIndex)

+(NSMutableDictionary *)createDictionaryForSectionIndex:(NSArray *)array

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    for (char firstChar = 'a'; firstChar <= 'z'; firstChar++)
    
        //NSPredicates are fast
        NSString *firstCharacter = [NSString stringWithFormat:@"%c", firstChar];
        NSArray *content = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF beginswith[cd] %@", firstCharacter]];
        NSMutableArray *mutableContent = [NSMutableArray arrayWithArray:content];

        if ([mutableContent count] > 0)
        
            NSString *key = [firstCharacter uppercaseString];
            [dict setObject:mutableContent forKey:key];
            NSLog(@"%@: %u", key, [mutableContent count]);
        
    

    return dict;


@end

/*

**Input:** 
"Aardvark", "Cabbage", "Boot", "Eggs", "Ape", "Aquaman", "Elephant", "Cat", "Bat", "Bubbles"

**Output:**
NSMutableDictionary
    key => 'A'
    object => "Aardvark", "Ape", "Aquaman"

    key => 'B'
    object => "Bat", "Boot", "Bubbles"

    key => 'C'
    object => "Cat", "Cabbage"

    key => 'E'
    object => "Elephant", "Eggs"

*/

然后我创建一个NSArray 实例变量来排序和存储来自indexDictionary 的所有键:

// this line should follow the creation of `indexDictionary`

sortedKeys = [[indexDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

// Output, in this case, is 'A', 'B', 'C', 'E'

您现在拥有为表设置索引所需的一切。实现以下方法(如果有些东西不能自我解释,请告诉我):

//this code assumes `sortedKeys` is not empty

#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return ([sortedKeys count]);



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSString *key = [sortedKeys objectAtIndex:section];
    return [[indexDictionary valueForKey:key] count];



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

    return ([sortedKeys objectAtIndex:section]);



-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

    return sortedKeys;



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

    return index;



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

    // preceding code...

    NSString *key = [sortedKeys objectAtIndex:indexPath.section];
    NSArray *array = [indexDictionary objectForKey:key];
    NSString *yourString = [array objectAtIndex:indexPath.row];

    cell.textLabel.text = yourString;

    // following code...

结果是一个带有索引的表,该索引会跳过没有关联数据的字母。

【讨论】:

这是一个非常棒的答案。谢谢。 如果你有一个字典数组而不是一个字符串数组,你唯一需要做的不同就是将你的谓词字符串更新为name beginswith[cd] %@而不是SELF beginswith[cd] %@。这将按每个字典的名称字段对您的字典数组进行排序。【参考方案2】:
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad

    [super viewDidLoad];
    NSMutableArray *temp = [[NSMutableArray alloc] init];
    NSMutableArray *temp2 = [[NSMutableArray alloc] init];
    for(int i = 0; i < tableListArray.count; i++)
    
        NSString *string = [tableListArray objectAtIndex:i];
        NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
        [dict setObject:string forKey:@"Name"];
        [dict setObject:[NSNumber numberWithInt:i] forKey:@"ID"];
        NSString *firstString = [string substringToIndex:1];
        if([temp2 containsObject:firstString] == NO || temp2.count == 0)
        
            if(temp2.count != 0)
            
                [temp addObject:temp2];
                [temp2 release];
                temp2 = [[NSMutableArray alloc] init];
            
            [temp2 addObject:firstString];
        
        [temp2 addObject:dict];
        [dict release];
    
    [temp addObject:temp2];
    detailListArray = [[NSArray alloc] initWithArray:temp];
    [temp release];
    [temp2 release];


#pragma mark -
#pragma mark Table view data source
- (NSInteger)tableView:(UITableView *)tableView 
sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index

    int i = 0;
    for(NSArray *array in detailListArray)
    
        NSString *string = [array objectAtIndex:0];
        if([string compare:title] == NSOrderedSame)
            break;
        i++;
    
    return i;


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return detailListArray.count;


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

    NSArray *array = [detailListArray objectAtIndex:section];
    return [array objectAtIndex:0];


- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView 

    NSMutableArray *titleArray = [NSMutableArray array];
    [titleArray addObject:@"A"];
    [titleArray addObject:@"B"];
    [titleArray addObject:@"C"];
    [titleArray addObject:@"D"];
    [titleArray addObject:@"E"];
    [titleArray addObject:@"F"];
    [titleArray addObject:@"G"];
    [titleArray addObject:@"H"];
    [titleArray addObject:@"I"];
    [titleArray addObject:@"J"];
    [titleArray addObject:@"K"];
    [titleArray addObject:@"L"];
    [titleArray addObject:@"M"];
    [titleArray addObject:@"N"];
    [titleArray addObject:@"O"];
    [titleArray addObject:@"P"];
    [titleArray addObject:@"Q"];
    [titleArray addObject:@"R"];
    [titleArray addObject:@"S"];
    [titleArray addObject:@"T"];
    [titleArray addObject:@"U"];
    [titleArray addObject:@"V"];
    [titleArray addObject:@"W"];
    [titleArray addObject:@"X"];
    [titleArray addObject:@"Y"];
    [titleArray addObject:@"Z"];
    return titleArray;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    NSArray *array = [detailListArray objectAtIndex:section];
    return (array.count - 1);


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

    UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                    reuseIdentifier:@"CELL"] autorelease];
    NSArray *array = [detailListArray objectAtIndex:indexPath.section];
    NSDictionary *dict = [array objectAtIndex:indexPath.row + 1];
    cell.textLabel.text = [dict objectForKey:@"Name"];
    return cell;


#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    NSArray *array = [detailListArray objectAtIndex:indexPath.section];
    NSDictionary *dict = [array objectAtIndex:indexPath.row + 1];
    int entryID = [[dict objectForKey:@"ID"] intValue];
     // Do what ever you want to do with the selected row here....

这是我在最近的一个项目中使用的代码。

【讨论】:

【参考方案3】:

我正在做一个项目,我需要针对同一问题的动态解决方案,所以我想出了这个解决方案,它只返回包含可用部分的字典。希望对某人有所帮助。

-(NSMutableDictionary *)getSortedDataWithArray:(NSArray *)dataArray
  NSMutableDictionary *allDataDictionary = [[NSMutableDictionary alloc]init];

  for(int i = 0 ; i< dataArray.count ;i++)

    NSString *currentStr = [[[dataArray objectAtIndex:i] substringToIndex:1] uppercaseString];
    NSArray *allKeysArray = allDataDictionary.allKeys;

    if([allKeysArray containsObject:currentStr])
        NSMutableArray *currentArray = [[NSMutableArray alloc] initWithArray:[allDataDictionary valueForKey:currentStr]];
        [currentArray addObject:[dataArray objectAtIndex:i]];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF beginswith[c] %@" ,currentStr];
        NSArray *finalArray = [currentArray filteredArrayUsingPredicate:predicate];
        [allDataDictionary setValue:finalArray forKey:currentStr];
    
    else
        NSMutableArray *finalArray = [[NSMutableArray alloc] initWithObjects:[dataArray objectAtIndex:i], nil];

        [allDataDictionary setValue:finalArray forKey:currentStr];
    
  
 return allDataDictionary;

【讨论】:

以上是关于从 NSArray 为 UITableView 创建索引的主要内容,如果未能解决你的问题,请参考以下文章

iOS:从 UITableView 动态添加数据到 NSArray

如何从使用 JSONKit 创建的 NSDictionary 中正确填充 UITableView NSArray?

将自定义对象的 NSArray 转换为按字母顺序划分的带有索引的 UITableView?

根据 NSDictionaries 的 NSArray 中的值为 UITableView 创建索引

如何在ios中使用NSDictionary将两个NSArray对象显示为UITableview的部分[重复]

为啥我不能在 uitableview 单元格中放置一个 nsarray