UITableViewCell 在首次加载时无法正确呈现

Posted

技术标签:

【中文标题】UITableViewCell 在首次加载时无法正确呈现【英文标题】:UITableViewCell not rendering properly on first load 【发布时间】:2015-05-28 16:43:57 【问题描述】:

一些背景: 我正在使用 UITableView 构建一个应用程序,该应用程序显示用户可以使用 UITableViewCell 的子类对其进行投票的民意调查列表。 UITableViewCell 子类有 5 个 IBOutlet UILabel:一个问题标签,然后是 4 个选择标签。民意调查可能有 2、3 或 4 个选项,因此我可能不会显示第 3 和/或第 4 选项标签。每个标签都将“Lines”设置为 0,这样如果文本太长,它们会自动换行。

按照本教程,我设置了布局约束以确保单元格具有动态高度:http://www.raywenderlich.com/87975/dynamic-table-view-cell-height-ios-8-swift

问题标签的内容拥抱优先级为 250,而所有选择标签的优先级为 251。 问题标签的 Content Compression Resistance 优先级为 751,而所有选项标签的优先级为 752。

当我第一次加载应用程序时,第一个民意调查的问题有太多的垂直填充,第一个选择会被省略号截断。 但是,当我向下滚动然后向上滚动时,它会自行修复:问题标签包含它的内容,第一个选择显示它的所有内容。

这是我制作的显示问题的 GIF(关注顶部单元格):

这是 Interface Builder 的屏幕截图(如果有帮助的话):

这是我用来填充单元格标签的代码:

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

    PollTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPollCellReuseId];
    Poll *poll = [self.polls objectAtIndex: indexPath.row];

    cell.questionLabel.text = poll.question;
    cell.choiceLabel1.text = [(Choice *)[poll.choices objectAtIndex:0] text];
    cell.choiceLabel2.text = [(Choice *)[poll.choices objectAtIndex:1] text];

    BOOL hasChoice3 = poll.choices.count > 2;
    cell.choiceLabel3.text = hasChoice3 ? [(Choice *)[poll.choices objectAtIndex:2] text] : @"";
    cell.choiceLabel3TopConstraint.constant = hasChoice3 ? 8 : 0;

    BOOL hasChoice4 = poll.choices.count > 3;
    cell.choiceLabel4.text = hasChoice4 ? [(Choice *)[poll.choices objectAtIndex:3] text] : @"";
    cell.choiceLabel4TopConstraint.constant = hasChoice4 ? 8 : 0;

    return cell;

为什么在第一次尝试时渲染不正确?

【问题讨论】:

如果在上面代码中返回单元格之前调用[cell layoutIfNeeded]会发生什么? 这似乎解决了它,但现在它抱怨表格中第二个单元格的自动布局:它不喜欢第三个和第四个选择标签之间的垂直间距 我降低了第 3 和第 4 个选项标签之间的垂直间距约束的优先级,现在一切似乎都很好。我是否以正确的方式解决这个问题?对于我想要完成的事情,这一切似乎有点老套。 【参考方案1】:

为我的表添加延迟 reloadData 已修复问题。

我用过,

self.tableView.rowHeight = UITableViewAutomaticDimension;

self.tableView.estimatedRowHeight = 500.0;

cell.layoutIfNeeded()返回单元格

之前

但添加延迟重新加载 tableView 为我解决了问题。该问题仅出现在 iPad 上。

DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) 
                self.tableView.reloadData()      
          

另一种替代解决方案对我有用,

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) 

                //Reload with delay
                self.tableView.reloadData()

                //Again reload with delay
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) 
                    self.tableView.reloadData()
                
            

【讨论】:

救了我的命,兄弟!非常感谢 致我们的 Objective-C 朋友:dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^ [self.tableView reloadData]; );【参考方案2】:

我也遇到了同样的问题并使用以下技巧解决了:

    extension UITableView 
    func reloadDataWithAutoSizingCellWorkAround() 
        self.reloadData()
        self.setNeedsLayout()
        self.layoutIfNeeded()
        self.reloadData()
    

【讨论】:

它有效...只是拯救我的一天。但我能找出原因吗? 感谢为我工作。没有第一次重载,真的有必要吗? 这对我也有用。谢谢。我发现只有最后一次重新加载是必要的。与此解决方案无关,但问题是在初始加载时 tableview 抱怨布局问题,但此后没有,尽管它是相同的单元格。【参考方案3】:

实施

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

并返回任何例如100,别忘了设置

self.tableView.rowHeight = UITableViewAutomaticDimension

viewDidLoad

【讨论】:

我不认为这是问题所在。我已经在这个 UITableView 的 ViewController 的viewDidLoad 中有这个:self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 180.0;【参考方案4】:

根据@sikhapol 的评论: 在返回-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath中的单元格之前执行[cell layoutIfNeeded]

解决问题

【讨论】:

以上是关于UITableViewCell 在首次加载时无法正确呈现的主要内容,如果未能解决你的问题,请参考以下文章

requirejs w/ knockoutjs w/ select2 无法在首次加载时更新 observable

StreamBuilder ListView 在首次加载时从 Firestore 返回空列表

如何在首次加载应用程序时隐藏主弹出视图?

使用 Open Sans 字体时,Chrome 在首次打印时无法正确打印

iPhone简介视图-仅在首次加载时加载[关闭]

Foundation 兜风仅在首次加载问题时启动