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

方案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+1
	NSInteger 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+1
	NSInteger 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.3 section下面的子内容是对的,这个没有问题的,因为现在的数据源是对的。

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会如何?


 在使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值