目录
cell的复用
手动(非注册)
自动(注册)
自定义cell
在iOS开发中,单元格复用是一种提高表格(UITableView)和集合视图(UICollectionView)滚动性能的技术。
当一个UITableViewCell或UICollectionViewCell首次需要显示时,如果没有可复用的单元格,则视图会创建一个新的单元格。一旦这个单元格滚动出屏幕,它就不会被销毁。相反,它被添加到一个对象池中。当表格需要显示一个新的单元格时,它会先检查对象池。如果对象池中有已经存在的单元格,表格就会取出这个单元格,然后使用新的数据重新配置这个单元格,而不是创建一个新的。
有两种方式实现cell的复用:
dequeueReusableCellWithIdentifier:意思是出列的可用的cell,即使用这个方法可以获取通过滚动创建过并放回对象池中的可以复用的cell对象。
用一个局部变量字符串来作为cell的id
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *strID = @"id";
UITableViewCell *cell = [_tabView dequeueReusableCellWithIdentifier: strID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: strID];
}
cell.textLabel.text = @"aaa";
return cell;
}
使用注册的方式实现单元格的复用,就不用判空。
在viewDidLoad中先对需要复用的cell使用registerClass进行注册,然后在创建cell的函数中使用dequeueReusableCellWithIdentifier获取可复用的cell,如果没有可复用的cell,就自动利用注册cell时提供的类创建新的一个cell并返回。
- (void)viewDidLoad
{
[super viewDidLoad];
// 如果使用 Nib 自定义 Cell
[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] forCellReuseIdentifier:@"myCell"];
// 如果使用代码自定义 Cell
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"myCell"];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *strID = @"id";
MyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier: strID];
cell.backgroundColor = [UIColor redColor];
return cell;
}
在iOS开发中,"自定义单元格"(Custom Cell)是指开发者根据具体的设计需求,创建特定样式和功能的单元格,这些单元格用于UITableView或UICollectionView中,以展示数据。
使用自定义单元格的原因主要包括:
个性化设计要求: 当系统提供的单元格样式无法满足应用的设计需求时,就需要通过自定义单元格来实现特定的界面和布局。
复杂的数据展示: 如果需要在单元格中显示复杂的数据结构(如图文混排、动态控件集合等),使用自定义单元格可以更灵活地控制数据的展示方式。
优化性能: 当列表视图中需要展示的单元格类型非常多样或者数据加载非常复杂时,通过精心设计的自定义单元格可以有效地提高滚动和渲染的性能。
在自定义cell的的时候,我们需要新建一个UITableViewCell,然后在该文件的.h文件中添加我们所需要的相关控件,要先创建一个self,然后在.m中重写一个初始化的initWithStyle:reuseIdentifier:方法,在该方法中,使用父类super的initWithStyle:reuseIdentifier:方法初始化self,然后为手动为该self的各个属性赋值,最后返回self。类似于前面学的内容的重写initWithXxx方法。
在添加当前控件到原视图上时,我们要将控件做为self.contentView的子视图。其中contentView是cell的subView,是内容视图。
实现完上面那个函数后,我们还需要实现一个控制其位置的函数——layoutSubviews,在该函数中我们可以设置各个控件的位置。
#import "ViewController.h"
#import "MyTableViewCell.h"
@interface ViewController ()
@end
static NSString *str = @"id";
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView = [[UITableView alloc] init];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.backgroundColor = [UIColor grayColor];
[_tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:str];
[self.view addSubview:_tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:str];
return cell;
}
@end
#import
NS_ASSUME_NONNULL_BEGIN
@interface MyTableViewCell : UITableViewCell
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *button;
@end
NS_ASSUME_NONNULL_END
#import "MyTableViewCell.h"
@implementation MyTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
self.label = [[UILabel alloc] init];
self.label.text = @"哈哈";
[self.contentView addSubview:_label];
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.contentView addSubview:_button];
return self;
}
- (void)layoutSubviews {
_label.frame = CGRectMake(0, 0, 70, 80);
_button.frame = CGRectMake(100, 0, 70, 70);
}