1. 程式人生 > >記一次簡單的UITableView卡頓優化

記一次簡單的UITableView卡頓優化

先說需求,要做一個類似這種的列表

標籤控制元件直接用的第三方

YZTagList

 不知道的可以去搜一下,當這不重要。

重要的是這個控制元件載入資料的時候非常影響列表滑動效果,造成卡頓,尤其是列表行數如果更多的話,

這也不是要說的重點,自己寫的控制元件也不一定就不耗效能,所以記一下我這次的處理方法。

先看一下cell程式碼:

 1 @interface PreferTableViewCell ()
2 @property (nonatomic, weak) UILabel *titleLabel; 3 @property (nonatomic, strong) YZTagList *tagList; 4 @end 5 6 @implementation PreferTableViewCell 7 8 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 9 if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
10 [self setupUI]; 11 } 12 return self; 13 } 14 - (void)setupUI { 15 UIView *lineView = [[UIView alloc] init]; 16 lineView.backgroundColor = [UIColor colorWithRed:246/255.0 green:247/255.0 blue:248/255.0 alpha:1.0]; 17 [self.contentView addSubview:lineView]; 18 [lineView makeConstraints:^(MASConstraintMaker *make) {
19 make.left.equalTo(self); 20 make.right.equalTo(self); 21 make.height.equalTo(10); 22 make.top.equalTo(self); 23 }]; 24 25 UILabel *titleLabel = [[UILabel alloc] init]; 26 titleLabel.textColor = [UIColor blackColor]; 27 titleLabel.font = [UIFont systemFontOfSize:15]; 28 [self.contentView addSubview:titleLabel]; 29 self.titleLabel = titleLabel; 30 [titleLabel makeConstraints:^(MASConstraintMaker *make) { 31 make.left.equalTo(self).offset(15); 32 make.top.equalTo(lineView.bottom).offset(10); 33 }]; 34 35 YZTagList *tagList = [[YZTagList alloc] init]; 36 tagList.isSort = NO; 37 tagList.backgroundColor = [UIColor whiteColor]; 38 // 高度可以設定為0,會自動跟隨標題計算 39 tagList.frame = CGRectMake(15, 50, SCREEN_WIDTH - 30, 0); 40 // 設定標籤背景色 41 tagList.tagBackgroundColor = [UIColor colorWithRed:246/255.0 green:247/255.0 blue:248/255.0 alpha:1.0]; 42 // 設定標籤顏色 43 tagList.tagColor = [UIColor colorWithHex:@"#303030"]; 44 45 tagList.tagFont = [UIFont systemFontOfSize:13]; 46 tagList.tagCornerRadius = 4; 47 tagList.clickTagBlock = ^(UIButton *btn){ 48 btn.selected = !btn.isSelected; 49 if (btn.isSelected) { 50 [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 51 [btn setBackgroundColor:[UIColor colorWithHex:@"#7676FD"]]; 52 } else { 53 [btn setTitleColor:[UIColor colorWithHex:@"#303030"] forState:UIControlStateNormal]; 54 [btn setBackgroundColor:[UIColor colorWithRed:246/255.0 green:247/255.0 blue:248/255.0 alpha:1.0]]; 55 } 56 }; 57 [self.contentView addSubview:tagList]; 58 59 self.tagList = tagList; 60 } 61 - (void)setTitle:(NSString *)title { 62 _title = title; 63 self.titleLabel.text = title; 64 } 65 - (void)setTags:(NSArray *)tags { 66 _tags = tags; 67 68 if (self.tagList.tagArray.count > 0) { 69 return; 70 } 71 [self.tagList addTags:tags]; 72 } 73 + (CGFloat)calcHeight:(NSArray *)tags { 74 YZTagList *tagList = [[YZTagList alloc] init]; 75 tagList.frame = CGRectMake(15, 50, SCREEN_WIDTH - 30, 0); 76 tagList.tagFont = [UIFont systemFontOfSize:13]; 77 tagList.tagCornerRadius = 4; 78 [tagList addTags:tags]; 79 return tagList.tagListH + 45 + 21; 80 } 81 @end


然後是VC程式碼:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.tags.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *ID = [NSString stringWithFormat:@"%ld%ld",indexPath.section,indexPath.row];
    PreferTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[PreferTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }
    cell.title = @"11111111"; 
    cell.tags = self.tags[indexPath.row];
    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat height = 0;
    height = [[self.cellheightCache objectForKey:[NSString stringWithFormat:@"%ld%ld",indexPath.section,indexPath.row]] floatValue];
    if (height == 0) {
        height = [PreferTableViewCell calcHeight:self.tags[indexPath.row]];
        [self.cellheightCache setObject:@(height) forKey:[NSString stringWithFormat:@"%ld%ld",indexPath.section,indexPath.row]];
    }
    return height;
}

前提:tags是一個二維陣列。

1.首先沒有使用cell重用機制,避免多次

[self.tagList addTags:tags];

影響滑動效果,反正標籤佔用記憶體微乎其微。

然後:

if (self.tagList.tagArray.count > 0) { return; }

一樣的目的。到這裡每個cell賦值只會發生一次。並且cell檢視均快取在記憶體中了。

2.然後是計算行高,計算行高需要用到一個類方法,程式碼寫的很清楚了,直接用

YZTagList

算出來並返回。然後用一個可變字典將高度快取起來,這樣保證高度也只會計算一次。

3.當然了,我的標題順序並不是程式碼執行順序。