UITableView初窥 - 绑定数据源、代理、修改、全局刷新、局部刷新

UITableView是iOS开发中最常用的控件之一,诸如: UITableViewStyleGrouped样式的

grouped样式

或者UITableViewStylePlain样式的

plain样式

在我们日常使用的app中,新浪微博、微信、QQ等软件都使用了UITableView作为消息和联系人的列表。 下面我做了一个小demo来介绍UITableViewStylePlain样式的商品目录应用程序。

1. 打开XCode (我用的4.6版本),新建一个simple view的项目(空项目也可以,我比较懒)。

2. 新建一个类作为我们的模拟数据模型 product

 1 //MCProduct.h
 2 //MC是我项目名的前缀,你们可以忽略。。。
 3 
 4 @interface MCProduct : NSObject
 5 
 6 @property (nonatomic,copy) NSString *name; //商品名
 7 @property (nonatomic,copy) NSString *icon; //商品图标
 8 
 9 //快速创建MCProduct对象
10 +(id)productWithName:(NSString*)name icon:(NSString*)icon; 
11 
12 @end
13 
14 //MCProduct.m
15 
16 #import "MCProduct.h"
17 
18 @implementation MCProduct
19 
20 +(id)productWithName:(NSString *)name icon:(NSString *)icon{
21     MCProduct *product = [[MCProduct alloc]init];
22     product.icon = icon;
23     product.name = name;
24     return product;
25 }
26 
27 @end

 

3. 开始创建UITableView

  1 //MCViewController.h
  2 
  3 @interface MCViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
  4 @end
  5 //MCViewController.m
  6 
  7 #import "MCViewController.h"
  8 #import "MCProduct.h"
  9 
 10 //设置UITableView的数据源与代理,需要实现
 11 //UITableViewDataSource,UITableViewDelegate接口
 12 //这个就不解释了,顾名思义了
 13 @interface MCViewController () 
 14 {
 15     NSArray *array;
 16     NSMutableArray *_array;
 17     UITableView *_tableView;
 18 }
 19 
 20 @end
 21 
 22 // 初始化数据方法,大家可以忽略不计,没必要细看
 23 - (MCProduct*)makeModelWithName:(NSInteger)name icon:(NSString*)icon{
 24     MCProduct *product = [MCProduct productWithName:[NSString stringWithFormat:@"第%d本书",name] icon:icon];
 25     return product;
 26 }
 27 
 28 - (void)viewDidLoad
 29 {
 30     [super viewDidLoad];
 31 
 32     //模拟添加10条数据
 33     _array = [[NSMutableArray alloc]init];
 34     for(int i=0;i<10;i++){
 35         int rvalue = (arc4random() % 9) + 1;
 36         MCProduct *p = [self makeModelWithName:i icon:[NSString stringWithFormat:@"%i",rvalue]];
 37         [_array addObject:p];
 38     }
 39     array = [[NSArray alloc]initWithArray:_array];
 40 
 41     //设置UITableView的样式、设置UITableView的代理及数据源
 42     //UITableViewStylePlain为通讯录
 43     //UITableViewStyleGrouped为iPhone设置的样式 - 分组样式
 44     //这个大家可以自己去实践了看效果
 45     _tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
 46     _tableView.dataSource = self;
 47     _tableView.delegate = self;
 48     [self.view addSubview:_tableView];
 49 }
 50 
 51 // 如果使用UITableViewStyleGrouped样式来分组,则这个方法返回一共有多少组
 52 //- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
 53 //    return 一个int数字;
 54 //}
 55 
 56 // 代理方法,指定某一组显示多少行,使用UITableViewStylePlain默认为一组
 57 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
 58     return array.count;
 59     //UITableViewStyleGrouped的使用方法:
 60     // if (section == 0){        //第0组
 61     //     return 2;             //2行内容 0 =》 0、1
 62     // } else if (section == 1){ //第1组
 63     //     return 3;             //3行内容 1 =》 0、1、2
 64     // }
 65 }
 66 
 67 // 某一组某一行的高度,用法同上,参数不同
 68 // indexPath.section 组
 69 // indexPath.row 行
 70 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
 71     return 50; //假设所有行都为50高度
 72 }
 73 
 74 // 代理方法,设置某一组某一行要显示的内容,取组取行方法同上
 75 - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
 76     // 这里要特别注意,看代码段以外的标注1
 77     // 标注1对应内容开始
 78     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"f1"];
 79     if(cell == nil){
 80         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"f1"];
 81     }
 82     // 标注1对应内容结束
 83 
 84     // 行最右边的按钮样式,如iPhone设置里的 > 箭头
 85     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 86 
 87     // 填充数据
 88     MCProduct *p = array[indexPath.row];
 89     cell.textLabel.text = p.name;
 90     cell.detailTextLabel.text = [NSString stringWithFormat:@"这是第%d本书的详细简介",indexPath.row];
 91     cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png",p.icon]];
 92 
 93     // 返回 UITableViewCell ,代理会自动加入到 UITableView
 94     return cell;
 95 }
 96 
 97 // 代理方法,当某一组某一行点击时调用此方法
 98 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
 99 
100     // 下面是关于UIAlertView的用法,
101     UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"注意" message:@"修改数据" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
102     alert.alertViewStyle = UIAlertViewStylePlainTextInput;
103     alert.tag = indexPath.row;
104     [alert textFieldAtIndex:0].text = ((MCProduct*)array[indexPath.row]).name;
105     [alert show];
106 }
107 
108 // 响应alertView的点击事件
109 - (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
110     // 0 为 cancelButton
111     if(0 == buttonIndex) return;
112     MCProduct *product = (MCProduct*)array[alertView.tag];
113     product.name = [alertView textFieldAtIndex:0].text;
114 
115     // 这里要特别注意,看代码段以外的标注2
116     // 标注2对应内容开始
117     NSIndexPath *path = [NSIndexPath indexPathForRow:alertView.tag inSection:0];
118     [_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationFade];
119     // 标注2对应内容结束
120 
121 }

 

 

标注1 Apple公司非常注重性能。在我初始化数据时,如果模拟了1W条数据,它并不会一次全加载进来,而是显示多少加载多少。

打个比方,我设置每一天的高度为50,而我UITableView的高度为200,那只会显示4条记录,delegate方法只会调用4次

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

 

当用户往上拉操作时,加载下面的内容。大家可以在这个方法里NSLog一下,看看效果。 当我往下拉了一段以后,看不见的Cell会被扔到缓存中,以便下一次的重用。

1 [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"f1";

 

这里的reuseIdentifier参数就是一个身份标识,如果没有这个标识,iOS是不会让这个失去区域的cell留在缓存中的。还有一点需要注意,不同style的cell,即使你知道他的标识,也不可重用。如你建立了两个UITableView,第一个UITableView使用UITableViewCellStyleDefault,标识f1;第二个UITableView使用UITableViewCellStyleSubtitle,标识f2。那第一个UITalbeView是无法使用f2标签的缓存的。

1 dequeueReusableCellWithIdentifier:(NSString *)identifier

 

方法是到缓存中取得cell,这样就可以避免重复开辟存储控件,提高效率。   标注2 当数据模型中的数据改变后,我们需要刷新一下UITalbeView列表。刷新有两种方式,这个大家自己看着怎么使用。 第一种:全局刷新 如果你的列表内容不是很多,或者变更的内容比较多,那全局刷新一下是可以的。

1 [tableView reloadData]

 

如果是像我这样的应用,需要局部刷新的,用reloadData有点浪费资源,就可以使用

1 - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

 

还可以加动画效果哦亲! indexPaths参数如下

1 NSIndexPath *path = [NSIndexPath indexPathForRow:alertView.tag inSection:0];

 

  好了,看完这篇文章的自己消化一下吧,领悟了就简单了。 代理方法名的话大家不要死记硬背,类声明的地方敲下 <UITableView,自然会提示有 UITableViewDelegate和 UITableViewDataSource,然后 command + 鼠标左键点进去看看成员变量和方法,英文别是小学水平的基本都看的明白吧。   哦。。。忘了还有两个实用代理方法,作用于 UITableViewStyleGrouped

1 //- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
2 //    return @"这里是头部文字";
3 //}
4 //
5 //-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
6 //    return @"这里是底部介绍,文字可以很长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长!";
7 //}

 

自己看吧,看不懂的是傻逼。 完整源代码 TestUITableView.zip

posted @ 2014-02-17 17:24  罗哥.ios  阅读(934)  评论(0编辑  收藏  举报