一胞皱、cell的重用機(jī)制
1邪意、why
同樣的cell會(huì)被創(chuàng)建很多次,這樣很浪費(fèi)系統(tǒng)的內(nèi)存反砌,既然是一樣的雾鬼,就可以拿來重復(fù)利用
2、what
當(dāng)滾動(dòng)列表時(shí)宴树,部分UITableViewCell會(huì)移出窗口策菜,這部分cell放到一個(gè)緩存池中,等待重用酒贬。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//1又憨、定義一個(gè)cell的標(biāo)識(shí) 補(bǔ)充:static關(guān)鍵字:使變量成為靜態(tài)的局部變量,即編譯時(shí)就為變量分配內(nèi)存锭吨,直到程序退出才釋放存儲(chǔ)單元蠢莺,只在本文件內(nèi)部有效,而其他文件不可連接或引用該變量零如。
static NSString *identifier = @"cell";
// 2躏将、從緩存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 3、如果緩存池中沒有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
//4考蕾、設(shè)置cell的數(shù)據(jù)
cell.textLabel.text = @"哈哈";
return cell;
}
一祸憋、刷新
1、全部刷新
[self.tableView reloadData];//刷新數(shù)據(jù)
2肖卧、刷新某一個(gè)cell
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:3 inSection:0];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];
3夺衍、刷新某一個(gè)section
NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:section];
[self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
二、獲取某個(gè)指定的cell
IndexFirstTableViewCell *firstcell = (IndexFirstTableViewCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
firstcell.firstview.addressLabel.text = @"獲取指定的cell";
三、cell的加載方式
3.1沟沙、系統(tǒng)自帶的
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//1河劝、定義一個(gè)cell的標(biāo)識(shí)
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的點(diǎn)擊無效果
}
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
/**
* 構(gòu)造方法(在初始化對象的時(shí)候會(huì)調(diào)用)
* 一般在這個(gè)方法中添加需要顯示的子控件
*/
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 讓自定義Cell和系統(tǒng)的cell一樣, 一創(chuàng)建出來就擁有一些子控件提供給我們使用
self.backgroundColor = [UIColor redColor];
}
return self;
}
-(void)setModel:(CustomModel *)model{
_model = model;
// 1.給子控件賦值數(shù)據(jù)
[self settingData];
// 2.設(shè)置frame
[self settingFrame];
}
/**
* 設(shè)置子控件的數(shù)據(jù)
*/
- (void)settingData
{
}
/**
* 設(shè)置子控件的frame
*/
- (void)settingFrame
{
}
@end
ViewController
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"cell";
// 1.取緩存中取
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 2.創(chuàng)建cell
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;//cell的點(diǎn)擊無效果
}
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和系統(tǒng)的cell一樣, 一創(chuàng)建出來就擁有一些子控件提供給我們使用
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)
其他都一樣颊咬,就是加載的時(shí)候用 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.創(chuàng)建cell
if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
// 如果找不到就從xib中創(chuàng)建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)];
五敞临、計(jì)算cell中文字的高度
/**
* 計(jì)算文本的寬高
*
* @param str 需要計(jì)算的文本
* @param font 文本顯示的字體
* @param maxSize 文本顯示的范圍
*
* @return 文本占用的真實(shí)寬高
*/
- (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName : font};
// 如果將來計(jì)算的文字的范圍超出了指定的范圍,返回的就是指定的范圍
// 如果將來計(jì)算的文字的范圍小于指定的范圍, 返回的就是真實(shí)的范圍
CGSize size = [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
return size;
}
//調(diào)用
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模型來計(jì)算cell的高度
如果cell的高度是固定的麸澜,那么最方便的方法就是用xib加載的方法挺尿,由于我們做的大多數(shù)項(xiàng)目的cell的高度都不是固定,圖片高度不一定炊邦,文字的高度也不一定编矾。所以要抽取一個(gè)frame模型來專門計(jì)算每個(gè)cell的高度。
步驟:
1.新建一個(gè)繼承自UITableViewCell的類
2.重寫initWithStyle:reuseIdentifier:方法
添加所有需要顯示的子控件(不需要設(shè)置子控件的數(shù)據(jù)和frame, 子控件要添加到contentView中)
進(jìn)行子控件一次性的屬性設(shè)置(有些屬性只需要設(shè)置一次, 比如字體\固定的圖片)
3.提供2個(gè)模型
數(shù)據(jù)模型: 存放文字?jǐn)?shù)據(jù)\圖片數(shù)據(jù)
frame模型: 存放數(shù)據(jù)模型\所有子控件的frame\cell的高度
4.cell擁有一個(gè)frame模型(不要直接擁有數(shù)據(jù)模型)
5.重寫frame模型屬性的setter方法: 在這個(gè)方法中設(shè)置子控件的顯示數(shù)據(jù)和frame
6.frame模型數(shù)據(jù)的初始化已經(jīng)采取懶加載的方式(每一個(gè)cell對應(yīng)的frame模型數(shù)據(jù)只加載一次)
六馁害、tableView展示數(shù)據(jù)的過程
調(diào)用數(shù)據(jù)源的下面方法得知一共有多少組數(shù)據(jù)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
調(diào)用數(shù)據(jù)源的下面方法得知每一組有多少行數(shù)據(jù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
調(diào)用數(shù)據(jù)源的下面方法得知每一行顯示什么內(nèi)容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;