当数据量特别大时,简单地以role进行分段,对实际查找的效率提升并不大。就像上一节开头所说,开发者可以根据球员名字的首字母进行分段,且分成26段。由于段数较多,可以使用UITableView的索引机制,在界面的右侧展示一条垂直的字母列表,使用户可以快速地在段与段之间进行切换。
新建一个继承自SimpleTableViewController的子类名为IndexedTableViewController,头文件声明如下:
1 #import "HBSimpleTableViewController.h" 2 #import "ChineseString.h" 3 #import "pinyin.h" 4 5 @interface HBIndexedTableViewController : HBSimpleTableViewController 6 { 7 //即表示每段的段名,也表示索引表的内容 8 NSArray *_indexTitles; 9 }
并且在SimpleTableViewController的数据源的基础上,对其进行改善优化,数据源将会得到重新制作,代码如下:
1 -(void)initData 2 { 3 [super initData]; 4 5 //将26个字母放进_indexTitles中 6 //表示段名,也表示索引表的内容 7 NSMutableArray *arrTmp=[NSMutableArray arrayWithCapacity:0]; 8 for (char c='A';c<='Z';c++) { 9 [arrTmp addObject:[NSString stringWithFormat:@"%c",c]]; 10 } 11 if (_indexTitles) { 12 _indexTitles=nil; 13 } 14 15 _indexTitles = [[NSArray alloc]initWithArray:arrTmp]; 16 17 //中文排序 18 //step1:获取要排序的数组 19 NSMutableArray *shouldSortArray=[NSMutableArray arrayWithArray:self.datasource]; 20 21 //step2:获取字符串中文字的拼音首字母并与字符串共同存放 22 NSMutableArray *chineseStringsArray=[NSMutableArray array]; 23 for (int i=0; i<[shouldSortArray count]; i++) { 24 ChineseString *chineseString=[[ChineseString alloc]init]; 25 26 HBPlayerInfo *onePlaer=[shouldSortArray objectAtIndex:i]; 27 28 chineseString.string=[NSString stringWithString:onePlaer.name]; 29 30 if(chineseString.string == nil) 31 { 32 chineseString.string = @""; 33 } 34 35 if(![chineseString.string isEqualToString:@""]) 36 { 37 NSString *pinYinResult=[NSString string]; 38 for (int j=0; j<chineseString.string.length; j++) { 39 NSString *singlePinyinLetter=[[NSString stringWithFormat:@"%c",pinyinFirstLetter([chineseString.string characterAtIndex:j])]uppercaseString]; 40 41 pinYinResult=[pinYinResult stringByAppendingString:singlePinyinLetter]; 42 } 43 chineseString.pinYin=pinYinResult; 44 } 45 else 46 { 47 chineseString.pinYin=@""; 48 } 49 [chineseStringsArray addObject:chineseString]; 50 } 51 52 //step2的输出 53 NSLog(@" 转换为拼音首字母后的NSString数组"); 54 for (int i=0; i<[chineseStringsArray count]; i++) { 55 ChineseString *chineseString=[chineseStringsArray objectAtIndex:i]; 56 NSLog(@"原String:%@----拼音首字母String:%@",chineseString.string,chineseString.pinYin); 57 } 58 59 //step3:按照拼音首字母对这些string进行排序 60 NSArray *sortDescriptors=[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"pinYin" ascending:YES], nil]; 61 62 [chineseStringsArray sortUsingDescriptors:sortDescriptors]; 63 64 //step3的输出 65 NSLog(@" 按照拼音首字母后的NSString数组"); 66 for(int i=0;i<[chineseStringsArray count];i++){ 67 ChineseString *chineseString=[chineseStringsArray objectAtIndex:i]; 68 NSLog(@"原String:%@----拼音首字母String:%@",chineseString.string,chineseString.pinYin); 69 } 70 71 //step4:如果有需要,再把排序好的内容从ChineseString类中提取出来 72 NSMutableArray *result=[NSMutableArray array]; 73 NSMutableArray *pinYinResult=[NSMutableArray array]; 74 for(int i=0;i<[chineseStringsArray count];i++){ 75 [result addObject:((ChineseString*)[chineseStringsArray objectAtIndex:i]).string]; 76 [pinYinResult addObject:((ChineseString *)[chineseStringsArray objectAtIndex:i]).pinYin]; 77 } 78 //Step4输出 79 NSLog(@" 最终结果:"); 80 for(int i=0;i<[result count];i++){ 81 NSLog(@"%@",[result objectAtIndex:i]); 82 } 83 84 85 //得到名字排好序的数据源后,需要将这些球员对象根据名字的首字母,进行分段 86 NSMutableArray *arrAll = [NSMutableArray arrayWithCapacity:0]; 87 88 //遍历26个字母 89 for(NSString *aIndexTitle in _indexTitles) 90 { 91 arrTmp=[[NSMutableArray alloc]initWithCapacity:0]; 92 93 //遍历球员对象,找到那些名字是当前字母的球员,加到arrTmp中去 94 for (ChineseString *oneChineseString in chineseStringsArray) { 95 NSString *pinYin=oneChineseString.pinYin; 96 NSString *firstPinYin=[pinYin substringToIndex:1]; 97 98 //不区分大小写比较 99 if([[firstPinYin lowercaseString] hasPrefix:[aIndexTitle lowercaseString]]) 100 { 101 [arrTmp addObject:oneChineseString]; 102 } 103 } 104 [arrAll addObject:arrTmp]; 105 } 106 //重置数据源,进行赋值 107 108 if(_datasource) 109 { 110 _datasource=nil; 111 } 112 _datasource = [[NSArray alloc] initWithArray:arrAll]; 113 }
数据源操作完,对于UITableView的数据源回调函数,需要为索引机制定做一套
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return _indexTitles.count; } //每段几行 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if(!self.datasource) { return 0; } NSArray *arrSectionPlayer=[self.datasource objectAtIndex:section]; return arrSectionPlayer.count; } //索引表内容 -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return _indexTitles; } //索引表与段之间的关联 -(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { //告诉我们一个段名和该段的序号 //我们需要返回一个对于索引表数组内容的序号 NSInteger count=0; for (NSString *aAlpha in _indexTitles) { if ([aAlpha isEqualToString:title]) { return count; } count++; } return 0; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"IndexTableViewCellId"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if(cell == nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } //数据源有两层,需要注意获取特定球员对象的方法 ChineseString *chineseString=nil; NSArray *arrSectionPlayer = [self.datasource objectAtIndex:indexPath.section]; if(arrSectionPlayer && arrSectionPlayer.count>indexPath.row) { chineseString=[arrSectionPlayer objectAtIndex:indexPath.row]; } if(chineseString) { cell.textLabel.text=chineseString.string; } return cell; }
另外,段名并非一定需要实现其数据源回调函数,使用代理回调函数也能够对段名进行配置,代码如下:
#pragma mark- #pragma mark TableView delegate //段名高22px高 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 22.0f; } -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { //使用UILabel来显示段名 NSString *strHeaderTitle = @""; UILabel *labHeaderView = [[UILabel alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 22.0f)]; if(_indexTitles && section < _indexTitles.count) { strHeaderTitle = [_indexTitles objectAtIndex:section]; } labHeaderView.text = [NSString stringWithFormat:@" %@",strHeaderTitle]; labHeaderView.textColor = [UIColor whiteColor]; labHeaderView.shadowColor = [UIColor grayColor]; labHeaderView.shadowOffset = CGSizeMake(1.0f, 1.0f); labHeaderView.font =[UIFont fontWithName:@"Helvetica" size:16.0f]; labHeaderView.backgroundColor=[UIColor colorWithRed:200.0f/255.0f green:200.0f/255.0f blue:200.0f/255.0f alpha:1.0f]; return labHeaderView; }
运行程序,得到如图14.8所示的结果。