
[注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/
在IOS中,实现表格展示数据,最常用的做法就是使用UITableView.
@interface UITableView : UIScrollView <NSCoding>
UITableView继承自UIScrollView,所以支持垂直滚动,而且性能极佳(这个会在以后提到,支持重用cell)
UITableView有两种样式:分组和不分组
分组:UITableViewStyleGrouped
不分组:UITableViewStylePlain


@PRoperty (nonatomic, readonly) UITableViewStyle style; @property (nonatomic, assign) id <UITableViewDataSource> dataSource; @property (nonatomic, assign) id <UITableViewDelegate> delegate; @property (nonatomic) CGFloat rowHeight; // will return the default value if unset
1.UITableView需要一个数据源(dataSource)来显示数据(如上面代码)
2.UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等
@protocol UITableViewDataSource<NSObject> @required - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; @optional - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; // Editing // Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; // Moving/reordering // Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath: - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; // Index - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#") - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1)) // Data manipulation - insert and delete support // After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change // Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; // Data manipulation - reorder / moving support - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; @end
3.没有设置数据元的UITableView只是一个空的壳子,不会展示任何数据
4.上面代码是UITableViewDataSource协议的,凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源,此处我们一般选择控制器为数据源.
所以总结一下使用UITableView展示数据的步骤:
UITableViewDataSource协议中必须要实现的方法:
@required //每一组有多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) //每一行显示什么样的内容 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
下面这个方法不是必须要实现的,不实现默认就是1组
//一共有多少组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; //这个方法不是必须要实现的,如果不实现,就默认是一组
下面通过一个小例子来演示UITableView的使用

下图是应用代码结构及plist文件截图:

此处的plist文件相对于前面文章介绍的比较复杂,此处是字典中又包含字典,所以使用的字典转模型的方法与之前也有所不同.首先要将里面的字典先转化为模型,再转化外面的.
上图中标注的KZCar是汽车数据模型
上图中标注的KZCarGroup是汽车组的数据模型,下面附上代码,其中尤其要注意,这个复杂的数据模型的转化过程.
KZCar.h
1 // 2 // KZCar.h 3 // UI基础-06-05-19 4 // 5 // Created by hukezhu on 15/5/20. 6 // 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface KZCar : NSObject 12 13 /** 14 * 声明图片属性 15 */ 16 @property (nonatomic,copy) NSString *icon; 17 18 /** 19 * 声明名称属性 20 */ 21 @property (nonatomic,copy) NSString *name; 22 23 24 -(instancetype)initWithDict:(NSDictionary *)dict; 25 26 +(instancetype)carWithDict:(NSDictionary *)dict; 27 28 +(NSArray *)carsWithDict:(NSArray *)dictarray; 29 @end
KZCar.m
1 //
2 // KZCar.m
3 // UI基础-06-05-19
4 //
5 // Created by hukezhu on 15/5/20.
6 //
7 //
8
9 #import "KZCar.h"
10
11 @implementation KZCar
12
13 -(instancetype)initWithDict:(NSDictionary *)dict{
14
15 if (self = [super init]) {
16 //使用KVC
17 [self setValuesForKeysWithDictionary:dict];
18 }
19 return self;
20 }
21
22
23 +(instancetype)carWithDict:(NSDictionary *)dict{
24
25 return [[self alloc]initWithDict:dict];
26 }
27
28 //此处是里面的汽车数据模型,分析汽车数组转化的时候,发现此处只需要传入一个数组即可
29 +(NSArray *)carsWithDict:(NSArray *)dictarray{
30
31
32 NSMutableArray *tempArray = [NSMutableArray array];
33 for (NSDictionary *dict in dictarray) {
34 KZCar *car = [KZCar carWithDict:dict];
35 [tempArray addObject:car];
36 }
37 return tempArray;
38 }
39 @end
KZCarGroup.h
// // KZCarGroup.h // UI基础-06-05-19 // // Created by hukezhu on 15/5/20. // // #import <Foundation/Foundation.h> @interface KZCarGroup : NSObject /** * 声明一个汽车的属性 */ @property (nonatomic,strong)NSArray *cars; /** * 声明一个标题的属性 */ @property (nonatomic,copy)NSString *title; -(instancetype)initWithDict:(NSDictionary *)dict; +(instancetype)carGroupWithDict:(NSDictionary *)dict; +(NSArray *)carGroups; @end
KZCarGroup.m
1 //
2 // KZCarGroup.m
3 // UI基础-06-05-19
4 //
5 // Created by hukezhu on 15/5/20.
6 //
7 //
8
9 #import "KZCarGroup.h"
10 #import "KZCar.h"
11
12 @implementation KZCarGroup
13 -(instancetype)initWithDict:(NSDictionary *)dict{
14
15 if (self = [super init]) {
16 _title = dict[@"title"];
17
18 //将字典中的数组cars取出来
19 NSArray *array = dict[@"cars"];
20 _cars = [KZCar carsWithDict:array];
21 }
22 return self;
23 }
24
25 +(instancetype)carGroupWithDict:(NSDictionary *)dict{
26
27 return [[self alloc]initWithDict:dict];
28 }
29
30 +(NSArray *)carGroups{
31
32
33 NSString *path = [[NSBundle mainBundle]pathForResource:@"cars_total" ofType:@"plist"];
34 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
35
36 NSMutableArray *tempArray = [NSMutableArray array];
37 for (NSDictionary *dict in dictArray) {
38 KZCarGroup *carGroup = [KZCarGroup carGroupWithDict:dict];
39 [tempArray addObject:carGroup];
40 }
41 return tempArray;
42 }
43 @end
ViewController.m
1 //
2 // ViewController.m
3 // 05-car多数据
4 //
5 // Created by hukezhu on 15/5/20.
6 //
7
8
9
10
11 #import "ViewController.h"
12 #import "KZCarGroup.h"
13 #import "KZCar.h"
14
15 @interface ViewController ()<UITableViewDataSource>
16
17 @property (weak, nonatomic) IBOutlet UITableView *tableView;
18
19
20
21 @property(nonatomic,strong)NSArray *cars;
22 @end
23
24 @implementation ViewController
25
26 - (void)viewDidLoad {
27 [super viewDidLoad];
28
29 self.tableView.dataSource = self;
30 NSLog(@"%@",self.cars);
31
32 }
33 #pragma mark -数据源方法
34 /**
35 * 返回一共有多少组
36
37 */
38 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
39
40 return self.cars.count;
41 }
42
43 /**
44 * 返回每一组有多少行
45 *
46 */
47 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
48
49 KZCarGroup *carGroup = self.cars[section];
50 return carGroup.cars.count;
51 }
52
53 /**
54 * 返回每行显示什么样的数据
55 *
56 */
57 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
58
59 NSString *identity = @"yes";
60 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identity ];
61
62 if (cell == nil) {
63 cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identity];
64 }
65 //取出组模型
66 KZCarGroup *carGroup = self.cars[indexPath.section];
67 //取出行模型
68 KZCar *car = carGroup.cars[indexPath.row];
69
70 cell.imageView.image = [UIImage imageNamed:car.icon];
71 cell.textLabel.text = car.name;
72 return cell;
73 }
74
75
76 /**
77 * 设置头部biaoti
78 *
79 */
80 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
81
82 //取出组模型
83 KZCarGroup *carGroup = self.cars[section];
84 return carGroup.title;
85
86 }
87
88 /**
89 * 设置尾部描述
90 *
91 */
92 -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
93
94 //取出组模型
95 KZCarGroup *carGroup = self.cars[section];
96 return carGroup.title;
97
98 }
99 /**
100 * 懒加载数据
101 *
102 */
103 -(NSArray *)cars{
104
105 if (_cars == nil) {
106 _cars = [KZCarGroup carGroups];
107 }
108 return _cars;
109 }
110 @end