【问题标题】:iOS 8: UITableViewCell detail text not correctly updatingiOS 8:UITableViewCell 详细信息文本未正确更新
【发布时间】:2014-11-17 04:33:16
【问题描述】:

tl;dr:我可以让 detailTextLabel 在值更改时由 iOS 中的自动布局系统更新其大小吗?

自 iOS 8 以来,还有其他人对 UITableViewCell 中的 detailText 标签有问题吗?

我有一个包含文本和详细信息字符串的表格。最初,详细信息文本是一个空字符串 (@"")。在对编辑屏幕执行情节提要后,我返回详细文本的新值并更新它。我尝试在 viewWillAppear 中重新加载表格,以便在返回上一个视图时立即显示该值。

一旦表格视图再次可见,表格单元格将文本字段向上移动以为详细文本腾出空间,但不显示详细文本。在我返回编辑屏幕并再次返回之前,文本不会显示。

我为解决问题所做的工作: 看起来详细文本标签的自动布局没有按照我认为的那样正确更新,并记录了 detailTextLabel 的大小和构成框架证实了这一点。

我可以通过在 viewDidAppear 中运行 [table reloadData] 来强制更新文本,但这会给我留下我不喜欢的闪烁效果,而且看起来不专业。

编辑:我所做的其他事情:我还强制 detailTextLabel 使用 [cell.detailTextLabel sizeToFit] 重新调整自身大小。这会导致它显示,但在单元格中以奇怪的方式偏移。再次进入编辑页面后,detailTextLabel 修复了它的位置。

我创建了一个简单的项目作为 github 存储库,以准确显示我正在处理的内容:

https://github.com/acidaris/ios8_table_issue

我正在使用的视图控制器的主要代码也在下面。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.table reloadData]; 
}


- (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section {
    return 1; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {  
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
    
    cell.textLabel.text = @"This is a test";
    cell.detailTextLabel.text = self.value;
    
    CGRect frame = cell.detailTextLabel.frame;
    NSLog(@"detailTextLabel x=%f y=%f width=%f height=%f",
        frame.origin.x,frame.origin.y,frame.size.width,frame.size.height);
    return cell; 
}

单元格在 StoryBoard 中进行了原型设计,因此 dequeueReusableCellWithIdentifier: 选择的单元格始终被定义。此外,情节提要中的单元格类型设置为副标题,如果定义了初始值,它确实会显示。

如果有人能帮我解决这个问题,我将不胜感激。

部分解决方案

如果你是 UITableViewCell 的子类,你可以在布局完成后修改 detailTextLabel 的框架。这就是我所做的,它似乎奏效了,但是在 6 plus 上,我在 textLabel 和 detailTextLabel 之间得到了一条奇怪的分界线。 编辑:(我已经对此进行了调整。 ) 我不喜欢这个解决方案,但到目前为止,这是我遇到的最好的解决方案。呈现视图后不更新,比较简单。正如我上面所说,我会继续寻找更好的解决方案。

- (void)layoutSubviews {
  [super layoutSubviews]; 
  CGRect textFrame = self.textLabel.frame;
  [self.detailTextLabel sizeToFit];

  CGFloat x = textFrame.origin.x;
  CGFloat y = textFrame.origin.y + textFrame.size.height;

  CGSize detailSize = self.detailTextLabel.frame.size;
  CGRect newFrame = CGRectMake(x, y, detailSize.width, detailSize.height);

  self.detailTextLabel.frame = newFrame;
}

我还更新了我的 Github 项目以反映我当前的解决方案。 Edit3:这并不完美,因为它对于真正的自动布局框架有错误的值,但它目前适用于我的使用。

编辑 4:我已将 layoutSubviews 函数更新为更智能。它将调整大小以固定标签内的内容,并在相对于文本标签的 x/y 坐标内适当地定位标签。

【问题讨论】:

标签: ios objective-c uitableview autolayout viewwillappear


【解决方案1】:

遇到同样的问题。我的解决方案是在返回-tableView:cellFForRowAtIndexPath 末尾的单元格之前调用[cell layoutSubviews]。这对我有用,我发现没有必要在单元格子类中覆盖layoutSubviews

【讨论】:

  • 谢谢@pixbug!这在我更新单元格的 viewdidload 方法中也适用于我。我认为 layoutSubViews 可以在更新 detailTextLabel.text 后立即调用。 code
     self.dueDate.detailTextLabel.text = [dateFormatter stringFromDate:self.movi​​e.dueDate]; [self.dueDate layoutSubviews]; 
  • 这应该是公认的解决方案,在我的情况下,我使用带有静态单元格的情节提要,所以我没有 -tableView:cellFForRowAtIndexPath。但是在我修改每个单元格的内容后调用 [cell layoutSubviews] 会使单元格在视图加载后立即可见。
  • 不要直接调用 layoutSubviews。如果您需要立即更新单元格的布局,请调用 setNeedsLayout,然后调用 layoutIfNeeded。
  • 调用[cell layoutIfNeeded] 解决了这个问题,对我来说非常有效。如果需要强制布局,只需要调用setNeedsLayout即可。
【解决方案2】:

在情节提要中使用 segue 时,单元格未正确更新也有同样的问题。 试过了

[setNeedsLayout] and [layoutIfNeeded]

在视图和表格视图上,它不起作用。

[self.tableView reloadData] is in viewDidAppear, as it should.

然后我尝试了 pixbug 的建议,它奏效了。但是不应该直接使用 [layoutSubviews]。所以我尝试了单元格上的文档而不是 tableView 或视图建议的那些。

试过了

[cell setNeedsLayout] 

但这不起作用。

试过

[cell layoutIfNeeded] 

这对我有用。

我把这个放在返回单元格之前。

【讨论】:

【解决方案3】:

我在 iOS 8 故事板中遇到了同样的问题(未启用自动布局)。

我有一个表格视图,底部有一个静态表格视图单元格。在 IB 中,我在表格单元格的内容区域中添加了一些空格(样式:“Right Detail”)。然后在代码 (ViewDidLoad) 中,我更新了该单元格的内容...

self.copyrightsCell.detailTextLabel.text = @"<a string>";

没有 IB 空间,单元格在纵向模式下是不可见的。

但是有了最初的空格,单元格的内容以后会正确显示。

希望这对某人有所帮助。

【讨论】:

    【解决方案4】:

    我也有同样的问题。 我确定数据可用并分配给 cell.detailTextLabel.text 我注意到,一旦分配了一个值,那么如果在返回 tableView 时更改了值,则不会闪烁。 所以在我看来,只有在第一次为 detailTextLabel 赋值时存在问题。

    【讨论】:

    • 是的,我仍然无法为这个问题找到一个好的解决方案。如果我在 viewWillAppear 和 viewDidAppear 期间执行重新加载,我可以让该值出现,但它是在显示视图后设置的,因此该值为空白,然后设置。 (正如你所说,第一次显示就很好了)。
    • 我可能有部分解决方案,请参阅上面的编辑。我并不完全喜欢这个解决方案,但它确实会按照我的意愿更新文本。
    • 我发现当我滚动表格时 detailTextLabel.text 已从单元格中删除,即使在强制将其加载到 viewDidAppear 之后也是如此。
    • 您是否尝试过我在上面发布的主要问题正文中的修复解决方案(在自定义 UITableViewCell 中覆盖 layoutSubviews?)它并不完美,但它会将标签的框架强制设置为适当的值。您可以使用一些实验来查看应该将其设置为什么值,我的应用程序只需要大约一半帧的长度,所以 150.0 适合我。
    • 这似乎与 stackoverflow.com/questions/25793074/… 重复。解决方法是永远不要在标签中包含非空文本(即使在情节提要中),或者在上述答案中放入代码补丁,这是对 Apple 错误的一种快速修复。
    【解决方案5】:

    所以,我遵循了这条路线和许多其他路线。这让我找到了似乎正确的答案。我希望这对其他人有所帮助,因为自从 iOS 7 / 8 进行了某种更改以来,这让我发疯了。

    我的回答是将正常的处理代码放在 viewWillAppear 中并添加这个 [self.tableview layoutSubviews] 而不是 [self.tableView reload data]。我认为这与 Apple 在 iOS 7 / 8 中让事情变得更加可控有关。我在查看有关单元如何工作的一些信息时突然想到了这个想法。

    再次,我希望这可以帮助其他人解决这个烦人的问题。

    【讨论】:

      【解决方案6】:

      我在使用静态 UITableView 时遇到了类似的问题。我更改了标签的文本,但除非我单击单元格或执行任何强制更新其视图的操作,否则它不会在屏幕上更新。 我的解决方法是在更新文本后调用:

      tableView.reloadData()

      P.S 这没有任何意义;因为这是一个静态表格视图,我不知道它为什么起作用,但它确实起作用了!

      【讨论】:

        【解决方案7】:

        我认为如果您需要重新加载数据,这意味着表数据在创建时没有加载。

        您只需将数据加载到您的 tableview 所在的 viewdidload 中(或在 table view 获取其数据之前的其他地方),然后相应地创建单元格。

        通常,我只使用我正在使用的任何对象的数组,然后使用您可能知道的[array objectAtIndex:indexpath.row]

        另外,你前面的最后一段有一个看起来很重要的未完成句子。

        【讨论】:

        • 所以,如果我从 viewWillAppear 中删除 [self.table reloadData],第一次加载是正确的,但不会发生更新。如果我将 reloadData 添加到 viewDidLoad,我会看到旧数据闪烁,然后是新数据。这似乎不对。
        • 更新了最后一段,并对我已经尝试解决的问题进行了额外的编辑。
        【解决方案8】:

        使用 Xcode 6.3.2 (6D2105) OS X Yosemite 10.10.3 确认问题 我确保分配了正确的值,但还是第一次没有出现, 第二次演出。 cell.layoutSubviews() 对我来说似乎是合乎逻辑的,因为它看起来好像视图缺少刷新并且添加 layoutSubviews() 就可以了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-27
          • 1970-01-01
          相关资源
          最近更新 更多