方案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当中显示 有子元素的索引字母?原理应该很简单的,请看:
|
但是还会有问题:怎么把这个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会如何?
在使用