一 重用UITableViewCell
UITableView滑动过程中,屏幕底部的信息上移到屏幕,会创建UITableViewCell对象,当把头部的信息再下拉重回到屏幕时,UITableViewCell会重复创建。重复创建会消耗内存,影响性能,通过重用UITableViewCell机制,能有效的避免性能问题。
1.1 不良代码
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*************第一版 Car *****************/
//1.创建cell
//当cell出现在屏幕时会重建
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
//2.取出数据
GMCar *car = self.array[indexPath.section];
NSString *name =car.subCars[indexPath.row];
//3.设置数据
cell.textLabel.text =name;
return cell;
}
1.2 重用Cell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*************第二版 LOL*****************/
//1.缓冲池中找cell是否已经创建,避免重建
static NSString * identifier = @"lol";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
//2.如果缓冲池中没有就创建cell
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
//NSLog(@"create new cell");
}
//3.设置数据
GMLOL *lol = self.dataArray[indexPath.row];
cell.textLabel.text = lol.name;
cell.textLabel.font = GMTextFont;
cell.detailTextLabel.text = lol.intro;
cell.detailTextLabel.font = GMDetailTextFont;
cell.detailTextLabel.numberOfLines=0;
cell.imageView.image = [UIImage imageNamed:lol.icon];
return cell;
}
注:申请内存需要时间,特别是在一定时间内频繁的申请内存将会造成很大的开销,重用UITableViewCell是UITableView dataSource中需要重点注意的地方,采用重用机制会让tableView更加流畅。
二 避免UITavleViewCell contentView 重新布局
UITableViewCell 在创建时就要将布局布好,避免 UITableViewCell 的重新布局。
三 避免UITavleViewCell 子视图过多 和 视图渲染
添加的UITableViewCell的子视图不宜过多(>4),过多的子视图对效率会参数影响。最好设置子视图为不透明的(opaque为YES),因为如果 子视图 不是 不透明的,view图层的叠加会开销一定的时间,影响到UITableView运行效率。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//1.缓冲池中找
static NSString * identifier = @"lol";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
//2.如果缓冲池中没有就创建cell
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
//3.设置子视图
CGFloat padding =10;
CGFloat labelW = 20;
CGFloat labelH = 30;
CGFloat labelY = 0;
for (int i=0; i<=10; i++) {
UILabel *label = [[UILabel alloc] init];
//设置文本位置
label.frame = CGRectMake((labelW+padding)*i, labelY, labelW, labelH);
//设置背景颜色
label.backgroundColor = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1];
//设置文本内容
label.text = [NSString stringWithFormat:@"%d",i];
label.opaque = YES;//默认是YES
[cell.contentView addSubview:label];
}
return cell;
}
子视图小于3时顺畅 子视图为10时,拖拽界面有点颠簸
四 LOL 代码区
注意点: UITableViewCell 重用,根据文本高度设置Cell
4.1代码
// ===== lol 类
@interface GMLOL : NSObject
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *intro;
-(instancetype)initWithDict:(NSDictionary *)dict;
+(instancetype)lolWithDict:(NSDictionary *)dict;
@end
@implementation GMLOL
-(instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+(instancetype)lolWithDict:(NSDictionary *)dict
{
return [[self alloc]initWithDict:dict];
}
@end
#import "ViewController.h"
#import "GMCar.h"
#import "GMLOL.h"
#define GMTextFont [UIFont systemFontOfSize:20]
#define GMDetailTextFont [UIFont systemFontOfSize:13]
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
/**
* UITableView
*/
@property (nonatomic, strong) UITableView *tableView;
/**
* car 数组
*/
@property (nonatomic, strong) NSArray *array;
/**
* lol 数组
*/
@property (nonatomic, strong) NSArray *dataArray;
@end
@implementation ViewController
- (void)viewDidLoad {
/*************第一版 Car *****************/
/*
//1.UITableView 设置
//1.1 设置数据代理
self.tableView.dataSource = self;
//1.2 设置frame
self.tableView.frame = self.view.frame;
//1.3 设置代理
self.tableView.delegate = self;
//2.UITableView加入veiw
[self.view addSubview:self.tableView];
*/
/*************第二版 LOL*****************/
//1.UITableView 设置
//1.1 设置数据代理
self.tableView.dataSource = self;
//1.2 设置frame
self.tableView.frame = self.view.frame;
//1.3 设置代理
self.tableView.delegate = self;
//2.UITableView加入veiw
[self.view addSubview:self.tableView];
}
#pragma mark - 数据加载
/**
* 调用数据源以下方法获取一共有多少组数据
*
* @param tableView <#tableView description#>
*
* @return <#return value description#>
*/
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
/*************第一版 Car *****************/
//return self.array.count;
/*************第二版 LOL*****************/
return 1;
}
/**
* 调用数据源方法获取每一组有多少行数据
*
* @param tableView tableView description
* @param section <#section description#>
*
* @return <#return value description#>
*/
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
/*************第一版 Car *****************/
//GMCar *car = self.array[section];
//return car.subCars.count;
/*************第二版 LOL*****************/
return self.dataArray.count;
}
/**
* 调用数据源方法获取每一行显示什么内容
*
* @param tableView <#tableView description#>
* @param indexPath <#indexPath description#>
*
* @return <#return value description#>
*/
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*************第一版 Car *****************/
/*
//1.创建cell
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
//2.取出数据
GMCar *car = self.array[indexPath.section];
NSString *name =car.subCars[indexPath.row];
//3.设置数据
cell.textLabel.text =name;
*/
//性能改进
/*************第二版 LOL*****************/
//1.缓冲池中找
static NSString * identifier = @"lol";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
//2.如果缓冲池中没有就创建cell
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
//NSLog(@"create new cell");
}
//3.设置数据
GMLOL *lol = self.dataArray[indexPath.row];
cell.textLabel.text = lol.name;
cell.textLabel.font = GMTextFont;
cell.detailTextLabel.text = lol.intro;
cell.detailTextLabel.font = GMDetailTextFont;
cell.detailTextLabel.numberOfLines=0;
cell.imageView.image = [UIImage imageNamed:lol.icon];
return cell;
}
#pragma mark - UITableViewDelegate
/**
* table 每一行的高度
*
* @param tableView <#tableView description#>
* @param indexPath <#indexPath description#>
*
* @return <#return value description#>
*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//计算行高
CGFloat padding =20;
GMLOL *lol = self.dataArray[indexPath.row];
CGSize nameSzie = [self sizeWithString:lol.name font:GMTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
CGSize detailSzie = [self sizeWithString:lol.intro font:GMDetailTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
return nameSzie.height + detailSzie.height +padding;
}
#pragma mark - 懒加载
-(UITableView *)tableView
{
if (!_tableView) {
//UITableViewStyleGrouped样式
//_tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStyleGrouped];
//UITableViewStylePlain 样式
_tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
}
return _tableView;
}
-(NSArray *)array
{
if (!_array) {
_array = [[NSArray alloc]init];
GMCar *c1 = [[GMCar alloc] init];
c1.title = @"德国品牌";
c1.desc = @"世界一流品牌";
c1.subCars = @[@"奥迪" , @"宝马"];
GMCar *c2 = [[GMCar alloc] init];
c2.title = @"日本品牌";
c2.desc = @"实用价值高";
c2.subCars = @[@"丰田" , @"本田"];
GMCar *c3 = [[GMCar alloc] init];
c3.title = @"欧美品牌";
c3.desc = @"高逼格";
c3.subCars = @[@"劳斯莱斯" , @"布加迪", @"兰博基尼"];
_array = @[c1, c3, c2];
}
return _array;
}
-(NSArray *)dataArray
{
if (!_dataArray) {
//1.获取路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"heros.plist" ofType:nil];
//2.加载数据
NSArray *array = [NSArray arrayWithContentsOfFile:path];
//3.模型转对象
NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
for (NSDictionary *dict in array) {
GMLOL *data = [GMLOL lolWithDict:dict];
[mutableArray addObject:data];
}
//4.赋值
_dataArray = mutableArray;
}
return _dataArray;
}
#pragma mark - 隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
return YES;
}
#pragma mark - 计算字体
/**
* 根据文本获取文本占用的大小
*
* @param string 文本
* @param font 字体
* @param maxSize 最大的宽高
*
* @return =
*/
- (CGSize)sizeWithString:(NSString *)string font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName:font};
// Size:文本能占用的最大宽高
// options: ios提供的计算方式
// attributes: 字体和大小
// context: nil
// 如果计算的文本超过了给定的最大的宽高,就返回最大宽高,如果没有超过,就返回真实占用的宽高
CGRect rect = [string boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
return rect.size;
}
@end
4.2展示