一 重用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 ()/** * 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展示