iOS UITableViewCell 中的砌体非常慢

Posted

技术标签:

【中文标题】iOS UITableViewCell 中的砌体非常慢【英文标题】:Masonry in iOS UITableViewCell is very slow 【发布时间】:2015-04-01 21:48:06 【问题描述】:

我正在开发一个适用于 iPhone 的 ios 应用程序,并且有一个 UITableView 和具有可变高度的自定义单元格。对于我使用 Masonry 的单元格布局:https://github.com/Masonry/Masonry。一切都按照我的喜好呈现,我唯一的问题是当一个新的单元格出现在屏幕上时会有一些延迟,这足以严重阻碍用户体验。我对执行时间进行了一些测试,似乎大部分延迟都在函数内部:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

在 iPhone 5 上执行时间约为十分之一秒。此外,我发现大部分时间都发生在函数中:

-(void)updateConstraints;

我的自定义 UITableViewCell 类。在这个函数中,我使用 Masonry 在单元格中设置各种视图约束。所以我基本上把这个滞后缩小到了砌体电话。如果您想知道,整个函数如下所示:

-(void)updateConstraints

    [super updateConstraints];

    [self.thumbnailImageView mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.equalTo(self.contentView.mas_top).offset(5);
        make.left.equalTo(self.contentView.mas_left).offset(5);
        make.right.equalTo(self.contentView.mas_right).offset(-5);
        make.height.equalTo(@(self.thumbnailImageView.frame.size.width)).with.priorityHigh();

    ];

    [self.likeButton mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.equalTo(self.thumbnailImageView.mas_bottom).offset(5);
        make.left.equalTo(self.captionTextView.mas_right);
    ];

    [self.dislikeButton mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.equalTo(self.thumbnailImageView.mas_bottom).offset(5);
        make.left.equalTo(self.likeButton.mas_right);
        make.right.equalTo(self.contentView.mas_right).offset(5);
    ];

    [self.captionTextView mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.equalTo(self.thumbnailImageView.mas_bottom).offset(5);
        make.left.equalTo(self.contentView.mas_left);
        make.right.equalTo(self.likeButton.mas_left);
        make.height.equalTo(@([self captionHeight]));
    ];

    [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.greaterThanOrEqualTo(self.captionTextView.mas_bottom).offset(5).with.priorityHigh();
        make.bottom.equalTo(self.contentView.mas_bottom);
        make.left.equalTo(self.contentView.mas_left).offset(5);
    ];

    [self.scoreLabel mas_makeConstraints:^(MASConstraintMaker *make) 
        make.left.equalTo(self.captionTextView.mas_right);
        make.top.equalTo(self.likeButton.mas_bottom);
        make.right.equalTo(self.contentView.mas_right);
    ];

    [self.numCommentsLabel mas_makeConstraints:^(MASConstraintMaker *make) 
        make.top.greaterThanOrEqualTo(self.scoreLabel.mas_top);
        make.bottom.equalTo(self.contentView.mas_bottom);
        make.right.equalTo(self.contentView.mas_right);
    ];

我想知道是否有任何方法可以减少执行时间并消除这种明显的滞后。我为每个单元格设置的约束与每个单元格的约束完全相同,但有一些例外。这只是 AutoLayout 的问题还是我正在做的事情非常错误?总的来说,这只是一个糟糕的方法吗?

【问题讨论】:

更新约束可以被多次调用。您应该确保不会多次添加所有约束。您还应该在末尾而不是开头调用[super updateConstraints] 【参考方案1】:

经过更多探索,我发现问题的根本原因是我的细胞没有得到适当的回收。我的 cellForRowAtIndexPath 函数最初看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *postTableIdentifier = @"PostTableCell";

    PostTableViewCell *cell = (PostTableViewCell *)[tableView dequeueReusableCellWithIdentifier:postTableIdentifier];
    if (cell == nil)
           
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:postTableIdentifier owner:self options:nil];
        cell = [nib objectAtIndex:0];
    

    //rest of function...

tableView 在这里查找重用标识符为 @"PostTableCell" 的单元格。但是,loadNibNamed: 函数没有设置单元格的重用标识符,因此 dequeReusableCellWithIdentifier: 找不到回收的单元格。我在这里找到了解决这个问题的好方法:How can I recycle UITableViewCell objects created from a XIB? 我会让它自己回答, 但我的新代码如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *postTableIdentifier = @"PostTableCell";

    PostTableViewCell *cell = (PostTableViewCell *)[tableView dequeueReusableCellWithIdentifier:postTableIdentifier];
    if (cell == nil)
    
        //register nib once
        [tableView registerNib:[UINib nibWithNibName:postTableIdentifier bundle:nil] forCellReuseIdentifier:postTableIdentifier];
        cell = (PostTableViewCell *)[tableView dequeueReusableCellWithIdentifier:postTableIdentifier];
    

    //rest of function...

【讨论】:

以上是关于iOS UITableViewCell 中的砌体非常慢的主要内容,如果未能解决你的问题,请参考以下文章

带有砌体的iOS AutoLayout,未能将子底部设置为父底部

砌体结构上的裂缝是啥裂缝

css 删除Enfold中的砌体动画

css 删除Enfold中的砌体动画

css 删除Enfold中的砌体动画

css 删除Enfold中的砌体动画