UITableView滑动过程中,屏幕底部的信息上移到屏幕,会创建UITableViewCell对象,当把头部的信息再下拉重回到屏幕时,UITableViewCell会重复创建。重复创建会消耗内存,影响性能,通过重用UITableViewCell机制,能有效的避免性能问题。
-(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; }
-(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更加流畅。
UITableViewCell 在创建时就要将布局布好,避免 UITableViewCell 的重新布局。
添加的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时,拖拽界面有点颠簸
注意点: UITableViewCell 重用,根据文本高度设置Cell
// ===== 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