iOS学习4_UITableView的使用
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 () <UITableViewDataSource,UITableViewDelegate> { 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。