记一次简单的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.当然了,我的标题顺序并不是代码运行顺序。

猜你喜欢

转载自www.cnblogs.com/alan12138/p/10238909.html