IOS 表视图(UITableVIew)的使用方法(3)名单的索引显示

当数据量特别大时,简单地以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(@"\n\n\n转换为拼音首字母后的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(@"\n\n\n按照拼音首字母后的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(@"\n\n\n最终结果:");
 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所示的结果。

posted @ 2014-04-16 16:58  haibo wang  阅读(654)  评论(0编辑  收藏  举报