关于使用UILocalizedIndexedCollation 实现tableview的边索引

来源:互联网 发布:有趣的数学问题 知乎 编辑:程序博客网 时间:2024/04/30 18:23

方案A:基本型,按步就班完成各个实现,就可以实现带索引功能的tableview了,最佳参考就是apple自带的sample code

==== ====

下面的代码就启动了view,继承自uitableviewcontroller

rootViewController.timeZonesArray = timeZones;    //有定义    //- (void)setTimeZonesArray:(NSMutableArray *)newDataArray {    //setter代码会被执行// Configure and display the window.[window addSubview:[navigationController view]];        [window makeKeyAndVisible];
setter所进行的工作,典型判断,是否一致,需要变化(如果内容是新的,而且不是空的,开始根据采用的UILocalizedIndexedCollation sectiontitles来构造分组过的tableview数据源,这点很重要,如何构造这个数据源,根据什么原则,比如首字母,最后一个字母等等方式,多可以在这个configursections中控制):

- (void)setTimeZonesArray:(NSMutableArray *)newDataArray {if (newDataArray != timeZonesArray) {[timeZonesArray release];timeZonesArray = [newDataArray retain];        //ARC will automatically give retain...}if (timeZonesArray == nil) {self.sectionsArray = nil;}else {        // 不是空的数组时候,需要配置下sections根据collation[self configureSections];}}
最简单的方式,就是没有复杂的分组判断抽取函数,依赖单一的属性或自身的情况:

- (void)configureSections {这个似乎比较基本,均得到26字母再加#self.collation = [UILocalizedIndexedCollation currentCollation];//Returns the list of section titles for the table view.... .... 27=26+1NSInteger index, sectionTitlesCount = [[collation sectionTitles] count];//tableView 会被分成27个section
NSMutableArray *newSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount]; 
//产生section的数组,根据大小。。。 。。。// Set up the sections array: elements are mutable arrays that will contain the time zones for that section.    // seperated sections...给每个section下增加一个数组对象。。for (index = 0; index < sectionTitlesCount; index++) {NSMutableArray *array = [[NSMutableArray alloc] init];[newSectionsArray addObject:array];[array release];}// Segregate the time zones into the appropriate arrays.for (TimeZoneWrapper *timeZone in timeZonesArray) {// Ask the collation which section number the time zone belongs in, based on its locale name.NSInteger sectionNumber = [collation sectionForObject:timeZone collationStringSelector:@selector(localeName)];        //根据属性localname给出timeZone的位置 ... ...         // Get the array for the section. 获得NSMutableArray *sectionTimeZones = [newSectionsArray objectAtIndex:sectionNumber];//  Add the time zone to the section.[sectionTimeZones addObject:timeZone];}    //可以没有,局部排序。。。完全看实际情况    // Now that all the data's in place, each section array needs to be sorted.for (index = 0; index < sectionTitlesCount; index++) {NSMutableArray *timeZonesArrayForSection = [newSectionsArray objectAtIndex:index];// If the table view or its contents were editable, you would make a mutable copy here.        //Sorts the objects within a section by their localized titles.        NSArray *sortedTimeZonesArrayForSection = [collation sortedArrayFromArray:timeZonesArrayForSection collationStringSelector:@selector(localeName)];// Replace the existing array with the sorted array.[newSectionsArray replaceObjectAtIndex:index withObject:sortedTimeZonesArrayForSection];      }self.sectionsArray = newSectionsArray;[newSectionsArray release];}
这里带来疑问,假如我们已有一个分组的大数组,那么是否还需要构造一次呢,目前来看,还要调整,因为你要匹配索引对应的 index,比如说,那个数组就应是27个元素的(每个element=section)。

还有一个就是section title是可以自己组合的 。

接下来,是几个标准的方法:根据点击的index的某个项目,可以获得title以及index,然后自动scroll到一个位置。

sectionForSectionIndexTitleAtIndex:index  of UILocalizedIndexedCollation

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {    //Returns the section that the table view should scroll to for the given index title.    return [collation sectionForSectionIndexTitleAtIndex:index];}
通过下面的方法就关联了所显示的indextitles和tableview的关系。在这个地方
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {    return [collation sectionIndexTitles];    }
在这里,可以把内容进行替换,例如显示符号而不是字母等方式:
sectionIndexTitlesForTableView
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {    for(id item in [collation sectionIndexTitles] )        NSLog(@"the titles: %@",item);  //

SimpleIndexedTableView[908:f803] the titles: #

return [collation sectionIndexTitles];
解下来就是一些常规的tableview的函数了,和普通的用法一致
titleForHeaderInSection

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

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

- (NSInteger)numberOfSectionsInTableView


//Returns an integer identifying the section in which a model object belongs.- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {    return [[collation sectionTitles] objectAtIndex:section];}
那么我们就要看看怎么定制化?

1. 数据已具备,那么可以通过编列collation的sectiontitles时候,处理一下,把现有数据对应到根据collation构造的datasource。

self.collation = [UILocalizedIndexedCollation currentCollation];//Returns the list of section titles for the table view.... .... 27=26+1NSInteger index, sectionTitlesCount = [[collation sectionTitles] count];NSLog(@"the total number: %d",sectionTitlesCount);NSMutableArray *newSectionsArray=[[NSMutableArray alloc] initWithCapacity:sectionTitlesCount]; //产生section的数组,根据大小。。。 。。。// Set up the sections array: elements are mutable arrays that will contain the time zones for that section.    // seperated sections...给每个section下增加一个数组对象。。   for (index = 0; index < sectionTitlesCount; index++) {       NSLog(@"%@", [[collation sectionTitles] objectAtIndex:index]);       switch (index) {           case 0:           { NSArray *group1=[[NSArray alloc] initWithObjects:@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",@"aaaa",@"abce",nil];                              [newSectionsArray addObject:group1];               break;}               case 1:           {                              NSArray *group2=[[NSArray alloc] initWithObjects:@"bccc",nil];                                             [newSectionsArray addObject:group2];               break;           }


2. 移出没有子数据的section,这点怎么处理?

   保证section的数目是正确的;保证section header显示内容是对的;section下面的子内容是对的;sectionForSectionIndexTitleAtIndex是能正常工作的

2.1删除其它空的子数组,保证section的数目是对的!

2.2而 section header,简单一点就是:

    NSString* object = [[sectionsArray objectAtIndex:section] objectAtIndex:0];    const char* objectChar = [object UTF8String];        return [[[NSString alloc] initWithFormat:@"%c", objectChar[0]] autorelease];     
通过拿出对象的首字母,反向显示出来,而不是之前的,通过sectiontitles来获得
[[collation sectionTitles] objectAtIndex:section];
2.3section下面的子内容是对的,这个没有问题的,因为现在的数据源是对的。

2.4保证能正确索引:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {    //return [collation sectionForSectionIndexTitleAtIndex:index]; 原标准代码,仅使用到这个index        // treat the last index (#) separatelly because NSString compare: thinks it's lower than any letter and will cause wrong results    if ([title isEqualToString:@"#"])        return [sectionsArray count] - 1;        // go through the sections and return the first one that matches the title or is AFTER it.     // If none is found, return the previous one    int nLastBefore = 0;    NSComparisonResult compareResult;    for (int i=0; i<[sectionsArray count]; i++)    {        NSString* sectionTitle = [self tableView:tableView titleForHeaderInSection:i];        compareResult = [[sectionTitle uppercaseString] compare:title];        NSLog(@"%@",[sectionTitle uppercaseString]);//随程序决定,大小写在比较时候重要        if (compareResult == NSOrderedSame || compareResult == NSOrderedDescending)            return i;                nLastBefore = i;    }// for i        return nLastBefore;}


那么还有问题就是只在sectiontitles当中显示 有子元素的索引字母?原理应该很简单的,请看:

if you want the indexes on the right side to only contain the letters that actually match some of your sections, here's what I did:

1. Add a NSMutableArray* member to your class (I named it sectionIndexArray)
2. - (NSArray *)sectionIndexTitlesForTableView: (UITableView *)tableView should look like this:

Code:
return [self sectionIndexArray];
3. Customize the getter method for sectionIndexArray

Code:
- (NSMutableArray*)sectionIndexArray{  if (sectionIndexArray == nil)  {    sectionIndexArray = [[NSMutableArray alloc] initWithArray:[collation sectionIndexTitles]];        // take every title and check if there's a section for it    int sectionsCount = [sectionsArray count];    for (int i=0; i<[sectionIndexArray count]; i++)    {      bool bExists = NO;      NSString* index = [sectionIndexArray objectAtIndex:i];      for (int j=0; j<sectionsCount; j++)      {        if ([index isEqualToString:[self tableView:nil titleForHeaderInSection:j]])        {          bExists = YES;          break;        }      }            if (bExists == NO)      {        [sectionIndexArray removeObjectAtIndex:i];        i --;      }    }// for i  }// if (sectionIndexArray == nil)    return sectionIndexArray;}


但是还会有问题:怎么把这个UI表现(sectiotitle)自定义呢。看看contacts的图:

The titles of the sections in that code come from the UILocalizedIndexedCollation object. If you want to have your own section titles that's fine. You still need to build a sectioned data model.If you don't want the index on the right side then the collation object probably isn't much help to you微笑. Regardless, that code builds a sectioned data model, which you also need if you want a sectioned table view.

还会有问题的,如果我们组合了searchbar在这个tableview会如何?如果使用uitableview动态而不是来自uitableviewcontroller会如何?


 在使用