从 NSArray 为 UITableView 创建索引

发布于 2024-12-01 02:19:38 字数 405 浏览 0 评论 0原文

我读过创建索引(uitableview 旁边的 az)的最佳方法是设置一个 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”等}。 ..?

I've read that the best way of creating an index (the a-z at the side of a uitableview) is to set up an array of nsdictionaries, where each dictionary corresponds to a section, and a rowValue key contains an array of the rows.

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

But how can this be created from an array of all the row titles - {”Aardvark”, “Ape”, “Aquaman”, ”Bat”, “Boot”, “Bubbles”, "Cat", "Cabbage" etc} ...?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

森林散布 2024-12-08 02:19:38

我最近有一个类似的目标,这就是我解决它的方法。与 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...
}

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

I recently had a similar objective and this is how I solved it. The advantage of this over Robin's solution is that it creates the index title array dynamically based on the content of your array and it won't include indices for empty sections (plus it's a little cleaner).

I created a category of NSMutableDictionary that takes an array of data as a parameter and returns an NSMutableDictionary (we'll call it indexDictionary and it should be an instance variable):

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

The category method:

@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"}

*/

Then I create an NSArray instance variable to sort and store all the keys from indexDictionary:

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

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

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

You now have everything you need to set up the index for your table. Implement the following methods (if something isn't self explanatory, just let me know):

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

The result is a table with an index that skips letters that have no associated data.

慢慢从新开始 2024-12-08 02:19:38
#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....
}

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

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

This is the code that I have used in one of the recent projects.

浅忆流年 2024-12-08 02:19:38

我正在开发一个项目,我需要同一问题的动态解决方案,所以我找到了这个解决方案,它返回仅包含可用部分的字典。希望它能帮助某人。

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

I was working on one project where I need dynamic solutions for same problem so I figure out this solutions which returns dictionary with only available sections. Hope it help someone.

-(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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文