tableView中一些常用的方法以及一些常见问题
一、cell的重用机制
1、why
同样的cell会被创建很多次,这样很浪费系统的内存,既然是一样的,就可以拿来重复利用
2、what
当滚动列表时,部分UITableViewCell会移出窗口,这部分cell放到一个缓存池中,等待重用。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//1、定义一个cell的标识 补充:static关键字:使变量成为静态的局部变量,即编译时就为变量分配内存,直到程序退出才释放存储单元,只在本文件内部有效,而其他文件不可连接或引用该变量。
static NSString *identifier = @"cell";
// 2、从缓存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 3、如果缓存池中没有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
//4、设置cell的数据
cell.textLabel.text = @"哈哈";
return cell;
}
一、刷新
1、全部刷新
[self.tableView reloadData];//刷新数据
2、刷新某一个cell
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:3 inSection:0];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];
3、刷新某一个section
NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:section];
[self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
二、获取某个指定的cell
IndexFirstTableViewCell *firstcell = (IndexFirstTableViewCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
firstcell.firstview.addressLabel.text = @"获取指定的cell";
三、cell的加载方式
3.1、系统自带的
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//1、定义一个cell的标识
static NSString *identifier = @"cell";
// 2、从缓存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 3、如果缓存池中没有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;//cell的点击无效果
}
cell.textLabel.text = @"哈哈";
return cell;
}
3.2、自定义方式(纯代码)
自定义的cell
.h文件
#import <UIKit/UIKit.h>
@class CustomModel;
@interface CustomTableViewCell : UITableViewCell
@property (nonatomic , strong) CustomModel *model;
@end
.m文件
#import "CustomTableViewCell.h"
#import "CustomModel.h"
@implementation CustomTableViewCell
/**
* 构造方法(在初始化对象的时候会调用)
* 一般在这个方法中添加需要显示的子控件
*/
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 让自定义Cell和系统的cell一样, 一创建出来就拥有一些子控件提供给我们使用
self.backgroundColor = [UIColor redColor];
}
return self;
}
-(void)setModel:(CustomModel *)model{
_model = model;
// 1.给子控件赋值数据
[self settingData];
// 2.设置frame
[self settingFrame];
}
/**
* 设置子控件的数据
*/
- (void)settingData
{
}
/**
* 设置子控件的frame
*/
- (void)settingFrame
{
}
@end
ViewController
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"cell";
// 1.取缓存中取
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 2.创建cell
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;//cell的点击无效果
}
cell.model = self.dataArray[indexPath.row];
return cell;
}
VC的中的cell再次简化
CustomTableViewCell.h文件
#import <UIKit/UIKit.h>
@class CustomModel;
@interface CustomTableViewCell : UITableViewCell
@property (nonatomic , strong) CustomModel *model;
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end
CustomTableViewCell.m文件
#import "CustomTableViewCell.h"
#import "CustomModel.h"
@implementation CustomTableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"status";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 让自定义Cell和系统的cell一样, 一创建出来就拥有一些子控件提供给我们使用
self.backgroundColor = [UIColor redColor];
}
return self;
}
@end
ViewController
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomTableViewCell *cell = [ CustomTableViewCell cellWithTableView:tableView];
//传递模型
return cell;
}
3.2、自定义方式(加载Xib)
其他都一样,就是加载的时候用 cell = [[[NSBundle mainBundle] loadNibNamed:@" CustomTableViewCell" owner:nil options:nil] firstObject];
+(instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *identifier = @"tg";
// 1.取缓存中取
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 2.创建cell
if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
// 如果找不到就从xib中创建cell
cell = [[[NSBundle mainBundle] loadNibNamed:@" CustomTableViewCell" owner:nil options:nil] firstObject];
}
return cell;
}
四、cell中的子控件重叠的解决办法
1、 [_titleLabel removeFromSuperview];//先移除再加载
2、 [self.backScrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];//移除原来的子控件
[self.backScrollView.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
五、计算cell中文字的高度
/**
* 计算文本的宽高
*
* @param str 需要计算的文本
* @param font 文本显示的字体
* @param maxSize 文本显示的范围
*
* @return 文本占用的真实宽高
*/
- (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName : font};
// 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
// 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
CGSize size = [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
return size;
}
//调用
CGSize nameSize = [self sizeWithString:_weibo.name font:[UIFont systemFontOfSize:15] maxSize:CGSizeMake(MAXFLOAT, 屏幕宽度-间隔)];
CGFloat nameLabelH = nameSize.height;
CGFloat nameLabelW = nameSize.width;
CGFloat nameLabelY = iconViewY + (iconViewH - nameLabelH) * 0.5;
self.nameLabel.frame = CGRectMake(nameLabelX, nameLabelY, nameLabelW, nameLabelH);
五、抽取frame模型来计算cell的高度
如果cell的高度是固定的,那么最方便的方法就是用xib加载的方法,由于我们做的大多数项目的cell的高度都不是固定,图片高度不一定,文字的高度也不一定。所以要抽取一个frame模型来专门计算每个cell的高度。
步骤:
1.新建一个继承自UITableViewCell的类
2.重写initWithStyle:reuseIdentifier:方法
添加所有需要显示的子控件(不需要设置子控件的数据和frame, 子控件要添加到contentView中)
进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
3.提供2个模型
数据模型: 存放文字数据\图片数据
frame模型: 存放数据模型\所有子控件的frame\cell的高度
4.cell拥有一个frame模型(不要直接拥有数据模型)
5.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
6.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)
六、tableView展示数据的过程
调用数据源的下面方法得知一共有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
调用数据源的下面方法得知每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
调用数据源的下面方法得知每一行显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;