在UITableView中,我们通常来展示各色各样的信息,这时,系统自带的cell形式就无法满足我们的需求了。此时,我们就需要用到自定义cell。
自定义cell
自定义的cell继承自UITableViewCell,同时,我们一般会声明一个模型类型的属性,我们通过重写这个属性的setter方法来对自定义cell上的控件进行UI展示。
自定义cell代码如下:
.h文件中
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell
//通常在cell中暴露一个属性接口,通过重写它的setter方法来完成对cell UI的布局。
@property (nonatomic, copy) NSString *stringModel;
@end
.m文件中
#import "CustomCell.h"
@interface CustomCell ()
//自定义cell所需展示的控件
@property (nonatomic, strong) UILabel *stringLabel;
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.stringLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 150, 30)];
self.stringLabel.textColor = [UIColor redColor];
[self.contentView addSubview:self.stringLabel];
}
return self;
}
- (void)setStringModel:(NSString *)stringModel
{
self.stringLabel.text = stringModel;
}
@end
cell的重用
自定义cell很简单,但是怎么使用它才是最重要的。我们知道,UITableView会展示大量的数据,如果展示的数据过多的话,每条数据都会需要一个cell,这样就加大了内存的消耗。幸运的是,UITableView带有cell重用机制,通过cell的重新利用,最大程度的减小了cell的创建,从而减少内存的消耗。
现在推荐使用注册的方式来完成cell的重用。该机制首先将一个cell实例放入一个缓存池中,然后UITableView在需要cell时,首先从缓存池中通过注册cell时的reuseid来找寻相同类型的cell,如果找到cell,则使用它,如果没有找到,则创建cell。一个cell在屏幕中不展示后,cell会被重新放回缓存池中。这样就达到了重用的效果。
cell的注册
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CustomCell"];
cell的使用
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell" forIndexPath:indexPath];
NSString *stringTemp = [[self.dataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.stringModel = stringTemp;
return cell;
总结
通过三篇博文,把UITableView的最常用的方法介绍了一遍,下面贴出源码。
自定义cell.h文件
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell
//通常在cell中暴露一个属性接口,通过重写它的setter方法来完成对cell UI的布局。
@property (nonatomic, copy) NSString *stringModel;
@end
自定义cell.m文件
#import "CustomCell.h"
@interface CustomCell ()
//自定义cell所需展示的控件
@property (nonatomic, strong) UILabel *stringLabel;
@end
@implementation CustomCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.stringLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 150, 30)];
self.stringLabel.textColor = [UIColor redColor];
[self.contentView addSubview:self.stringLabel];
}
return self;
}
- (void)setStringModel:(NSString *)stringModel
{
self.stringLabel.text = stringModel;
}
@end
ViewController.m文件
#import "ViewController.h"
#import "CustomCell.h"
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
//声明控件
@property (nonatomic, strong) UITableView *tableView;
//声明存储数据的数据结构
@property (nonatomic, strong) NSMutableArray *dataArray;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化控件
CGRect frame = CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
self.tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStyleGrouped];
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CustomCell"];
[self.view addSubview:self.tableView];
//设置代理
self.tableView.delegate = self;
self.tableView.dataSource = self;
//加载数据
[self loadData];
//创建用来改变编辑状态的按钮
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:self action:@selector(rightBtnAction:)];
}
#pragma mark - 按钮事件
- (void)rightBtnAction:(UIBarButtonItem *)sender
{
if (self.tableView.editing == YES) {
self.navigationItem.rightBarButtonItem.title = @"编辑";
}else{
self.navigationItem.rightBarButtonItem.title = @"完成";
}
self.tableView.editing = !self.tableView.editing;
}
#pragma mark - 加载数据
- (void)loadData
{
for (int i = 0; i < 4; i++) {
NSMutableArray *arrayTemp = [NSMutableArray array];
for (int j = 0; j < 4; j++) {
NSString *stringTemp = [NSString stringWithFormat:@"第%d块 第%d行", i, j];
[arrayTemp addObject:stringTemp];
}
[self.dataArray addObject:arrayTemp];
}
}
#pragma mark - UITableViewDelegate & UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.dataArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.dataArray objectAtIndex:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell" forIndexPath:indexPath];
NSString *stringTemp = [[self.dataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.stringModel = stringTemp;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//该条数据是这个块中最后一条数据
if ([[self.dataArray objectAtIndex:indexPath.section] count] == 1) {
//删除数据
[self.dataArray removeObjectAtIndex:indexPath.section];
//更新页面
NSIndexSet *set = [NSIndexSet indexSetWithIndex:indexPath.section];
[self.tableView deleteSections:set withRowAnimation:UITableViewRowAnimationRight];
}else{
//删除数据
[[self.dataArray objectAtIndex:indexPath.section] removeObjectAtIndex:indexPath.row];
//更新页面
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSString *stringTemp = [[self.dataArray objectAtIndex:sourceIndexPath.section] objectAtIndex:sourceIndexPath.row];
[[self.dataArray objectAtIndex:sourceIndexPath.section] removeObjectAtIndex:sourceIndexPath.row];
[[self.dataArray objectAtIndex:destinationIndexPath.section] insertObject:stringTemp atIndex:destinationIndexPath.row];
if ([[self.dataArray objectAtIndex:sourceIndexPath.section] count] == 0) {
[self.dataArray removeObjectAtIndex:sourceIndexPath.section];
[self.tableView reloadData];
}
}
#pragma mark - 懒加载
- (NSMutableArray *)dataArray
{
if (_dataArray == nil) {
self.dataArray = [NSMutableArray array];
}
return _dataArray;
}
@end