UITableView相当于Android里面的ListView,但功能却比ListView强大太多。
使用UITableView需要指定数据源和代理。
1.显示所有的行
遵守UITableViewDataSource协议,必须实现的方法有两个:
// 每一节里面有多少行- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section// 每行的View,这里是UITableViewCell- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
2.修改每行高度选中行
遵守UITableViewDelegate协议
// 选中某行- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath// 设置每行高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
3.编辑模式
UITableView设置编辑模式可以(滑动)删除、添加和移动每一行。只需要修改其属性editing
@property(nonatomic,getter=isEditing) BOOL editing;需要实现的方法
// 删除需要实现方法- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath// 移动需要实现的方法- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
4.性能优化
首先根据Identifier从可重用的队列中拿,如果没有再重新分配Cell的内存。
static NSString *ID =@"tableview";UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];if (cell == nil) { cell= [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:ID];}
5.例子
模型类:Shop.h
@interface Shop : NSObject@property (nonatomic, copy) NSString *icon;@property (nonatomic, copy) NSString *name;@property (nonatomic, copy) NSString *desc;@property (nonatomic) BOOL isChecked;+ (id)shopWithName:(NSString *)name icon:(NSString *)icon desc:(NSString *)desc;@end
Shop.m
#import "Shop.h"@implementation Shop+ (id)shopWithName:(NSString *)name icon:(NSString *)icon desc:(NSString *)desc{ Shop *shop = [[Shop alloc] init]; shop.icon = icon; shop.name = name; shop.desc = desc; return shop;}@end
自定义UITableViewCell
QhMyTableViewCell.h
@class Shop;@interface QhMyTableViewCell : UITableViewCell+ (QhMyTableViewCell *) myTableViewCell;@property (weak, nonatomic) IBOutlet UIImageView *imageViews;@property (weak, nonatomic) IBOutlet UILabel *title;@property (weak, nonatomic) IBOutlet UILabel *desc;@property (nonatomic) Shop * shop;@end
QhMyTableViewCell.m
@implementation QhMyTableViewCell+ (QhMyTableViewCell *) myTableViewCell{ NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"cell" owner:nil options:nil]; QhMyTableViewCell * view = views[0]; return view;}#pragma mark -重写set方法,设置数据- (void)setShop:(Shop *)shop{ self.imageView.image = [UIImage imageNamed:[shop icon]]; self.title.text = [shop name]; self.desc.text = [shop desc];}@end
QhViewController.h
@interface QhViewController : UIViewController@property (weak, nonatomic) IBOutlet UITableView *tableView;@property (weak, nonatomic) IBOutlet UIBarButtonItem *name;@property (weak, nonatomic) IBOutlet UIBarButtonItem *deleteIcon;@property (weak, nonatomic) IBOutlet UIBarButtonItem *allPick;//删除/编辑/反选按按钮的动作- (IBAction)remove:(UIBarButtonItem *)sender;- (IBAction)edit:(UIBarButtonItem *)sender;- (IBAction)allPickAction:(id)sender;// 使用加载xib然后通过连线的方式找到子控件进行设置,file owner设置为该控制器类时的输出口@property (weak, nonatomic) IBOutlet UIImageView *imageView;@property (weak, nonatomic) IBOutlet UILabel *titles;@property (weak, nonatomic) IBOutlet UILabel *descs;@end
QhViewController.m
@interface QhViewController (){ NSMutableArray * _shops; BOOL _flag;}@end@implementation QhViewController- (void)viewDidLoad{ [super viewDidLoad]; _shops = [NSMutableArray array]; Shop *shop1 = [Shop shopWithName:@"111" icon:@"001.png" desc:@"111,111,111"]; Shop *shop2 = [Shop shopWithName:@"222" icon:@"002.png" desc:@"222,222,222"]; Shop *shop3 = [Shop shopWithName:@"333" icon:@"003.png" desc:@"333,333,333"]; Shop *shop4 = [Shop shopWithName:@"444" icon:@"004.png" desc:@"444,444,444"]; Shop *shop5 = [Shop shopWithName:@"555" icon:@"005.png" desc:@"555,555,555"]; Shop *shop6 = [Shop shopWithName:@"666" icon:@"006.png" desc:@"666,666,666"]; Shop *shop7 = [Shop shopWithName:@"777" icon:@"007.png" desc:@"777,777,777"]; Shop *shop8 = [Shop shopWithName:@"888" icon:@"008.png" desc:@"888,888,888"]; Shop *shop9 = [Shop shopWithName:@"666" icon:@"006.png" desc:@"666,666,666"]; Shop *shop10 = [Shop shopWithName:@"777" icon:@"007.png" desc:@"777,777,777"]; Shop *shop11 = [Shop shopWithName:@"888" icon:@"008.png" desc:@"888,888,888"]; Shop *shop12 = [Shop shopWithName:@"666" icon:@"006.png" desc:@"666,666,666"]; Shop *shop13 = [Shop shopWithName:@"777" icon:@"007.png" desc:@"777,777,777"]; Shop *shop14 = [Shop shopWithName:@"888" icon:@"008.png" desc:@"888,888,888"]; [_shops addObjectsFromArray:@[shop1, shop2, shop3,shop4,shop5,shop6,shop7,shop8,shop9,shop10,shop11,shop12,shop13,shop14]];}//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView//{// return 1;//}#pragma mark 每一节里面有多少行- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ // 刷新数据时更改反选按钮的状态,没有数据时为不可选种状态 if (_shops.count > 0) { [_allPick setEnabled:YES]; } else [_allPick setEnabled:NO]; // 记录选中的行数 NSInteger i = 0; for (Shop * shop in _shops) { if (shop.isChecked) { i++; } } NSString * nameString; if (i>0) { nameString = [NSString stringWithFormat:@"已勾选(%d)",i]; }else nameString = @"已勾选"; self.name.title = nameString; // 只要有一行为选中状态就让删除按钮为可选状态 _flag = NO; for (Shop * shop in _shops) { if (shop.isChecked) { _flag = YES; } } if (_flag) { [_deleteIcon setEnabled:YES]; }else [_deleteIcon setEnabled:NO]; return _shops.count; }#pragma mark- 每行显示的cell#pragma mark 1表示使用系统自带的cell作为每一行的布局。#pragma mark 2表示加载自定义的xib文件,然后通过顺序或者tag找到每个子控件赋值。#pragma mark 3表示加载xib然后通过连线的方式找到子控件进行设置,file owner设置为控制器类。#pragma mark 最终采用的方式是自定义UITableViewCell,将xib对应的类修改为自己的类,连线。fileowner设置为nil。- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"tableview";//1 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; QhMyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) {//1 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];//2 NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"cell" owner:nil options:nil];//2 cell = views[0]; //3 NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"cell" owner:self options:nil];//3 cell = views[0]; cell = [QhMyTableViewCell myTableViewCell]; } NSLog(@"----->%p", cell);//2 UIImageView * imageView = cell.contentView.subviews[0];//2 UILabel * title = cell.contentView.subviews[1];//2 UILabel * desc = cell.contentView.subviews[2];//3 不需要,因为已经通过连线定义了输出口 Shop * shop = _shops[indexPath.row];//1 cell.imageView.image = [UIImage imageNamed:shop.icon];//1 cell.textLabel.text = [shop name];//1 cell.detailTextLabel.text = [shop desc]; //2 imageView.image = [UIImage imageNamed:shop.icon];//2 title.text = [shop name];//2 desc.text = [shop desc]; //3 _imageView.image = [UIImage imageNamed:shop.icon];//3 _titles.text = [shop name];//3 _descs.text = [shop desc]; [cell setShop:shop]; if (shop.isChecked) { cell.accessoryType = UITableViewCellAccessoryCheckmark; }else cell.accessoryType = UITableViewCellAccessoryNone; return cell;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 80;}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSInteger clickIndex = indexPath.row; Shop * shop = _shops[clickIndex]; BOOL b = shop.isChecked; shop.isChecked = !b; [_tableView reloadData];}#pragma mark 删除按钮的动作- (IBAction)remove:(UIBarButtonItem *)sender{ int i = 0; for (;i < _shops.count;) { Shop * shop = _shops[i]; if (shop.isChecked) { [_shops removeObjectAtIndex:i]; i = 0; }else i ++; } [_tableView reloadData];}#pragma mark 反选按钮的动作- (IBAction)allPickAction:(id)sender { for (Shop * shop in _shops) { BOOL b = shop.isChecked; shop.isChecked = !b; } [_tableView reloadData];}#pragma mark 编辑按钮的动作- (IBAction)edit:(UIBarButtonItem *)sender { //_tableView.editing = !self.tableView.editing; [_tableView setEditing:!self.tableView.editing animated:YES];}#pragma mark 删除对应的行 滑动删除的方法- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ // 从数据源删除 [_shops removeObjectAtIndex:indexPath.row]; // 刷新数据 [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];}#pragma mark 编辑模式下移动行要实现的方法- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ Shop * s = _shops[sourceIndexPath.row]; // 先删除源 [_shops removeObjectAtIndex:sourceIndexPath.row]; // 再插入到目的 [_shops insertObject:s atIndex:destinationIndexPath.row]; // 刷新数据}@end
在- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section方法中的数字表示使用了四种方式达到相同的目的。方式2和Android里面的思路一致。最终采用的方式可以实现松耦合有利于代码以后的重新利用。
1表示使用系统自带的cell作为每一行的布局。
2表示加载自定义的xib文件,然后通过顺序或者tag找到每个子控件赋值。
3表示加载xib然后通过连线的方式找到子控件进行设置,file owner设置为控制器类。
最终采用的方式是自定义UITableViewCell,将xib对应的类修改为自己的类,连线。fileowner设置为nil。