【问题标题】:AutoLayout breaks constraints when layoutIfNeeded() is called调用 layoutIfNeeded() 时 AutoLayout 会破坏约束
【发布时间】:2014-09-19 00:22:03
【问题描述】:

我正在尝试使用 Swift 使用 XCode6 在 UITableView 中实现动态高度 UITaleViewCell

通过以图形方式设置约束,我将单元格布局如下(屏幕截图来自 XCode5,因为 XCode6 上的 NDA)。我还将 BodyLabel 的 Line Break 属性设置为“自动换行”,并将行号设置为“0”以允许多行。

现在,如果我只是在 tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) 方法中设置单元格的内容,那么我可以正确获得动态高度行为。

但是,由于我遵循在线可用的教程(特别是 this one),我添加了另一种方法来使用 tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) 确定单元格的高度。 在我正在关注的教程中,它告诉我添加cell.layoutIfNeeded(),所以我也添加了它。

override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {

    var cell = tableView!.dequeueReusableCellWithIdentifier(kCellIdentifier) as GroupFeedCell

    // Configure the cell
    if let frc = self.fetchedResultsController {
        let feed = frc.objectAtIndexPath(indexPath) as GroupFeed
        cell.titleLabel.text = feed.name
        if let message = feed.message {
            cell.bodyLabel.text = message
        }
    }

    // Layout the cell
    cell.layoutIfNeeded()

    // Get the height
    var height : CGFloat = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    return height
}

但是,当我运行程序时,虽然表格视图仍然正确显示单元格的动态高度,但它显示的错误如下:

2014-07-27 13:59:22.599 FBGroups[4631:979424] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each    constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or    constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer    to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x17809e780 H:[UILabel:0x14fd12f50'Body Label Contents...']-(8)-|   (Names:    '|':UITableViewCellContentView:0x178185d70 )>",
    "<NSLayoutConstraint:0x17809e7d0 H:|-(8)-[UILabel:0x14fd12f50'Body Label Contents...']   (Names:    '|':UITableViewCellContentView:0x178185d70 )>",
    "<NSLayoutConstraint:0x17809ea50 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x178185d70(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17809e780 H:[UILabel:0x14fd12f50'Body Label Contents...']-(8)-|   (Names:     '|':UITableViewCellContentView:0x178185d70 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.  

我试图找出可能出了什么问题,并在上​​面花费了大量时间,我发现每当我删除 cell.layoutIfNeeded() 方法时,约束错误就会消失。

似乎在冲突的约束中,UIView-Encapsulated-Layout-Width 不是我添加的那个,除此之外,所有约束对我来说都是无辜的。我试图搜索可能产生UIView-Encapsulated-Layout-Width 约束的内容,但在我的情况下无法得到令人满意的解释。我想知道此错误消息的原因以及如何解决此问题。

另外,有人可以解释在计算单元格高度内调用cell.layoutIfNeeded() 方法的目的是什么,什么时候需要?大多数覆盖动态高度UITableViewCell 的教程都使用了这种方法,尽管我的程序在没有该方法调用的情况下仍能正确显示单元格,并且每当我尝试使用该方法时,都会导致异常。

【问题讨论】:

  • 你能解决这个问题吗?
  • 我也有这个问题。你修好了吗?
  • 你试过在标签上设置preferredMaximumWidth吗?

标签: uitableview swift autolayout xcode6


【解决方案1】:

cell.layoutIfNeeded() - 无需调用。 创建 IBOutlet 和 NSLayoutConstraint

【讨论】:

  • 您能在答案中添加一些细节吗?
【解决方案2】:

这似乎是苹果的一个错误。我使用一种解决方法,在运行时添加width 约束,就像这样。

- (void)configurateBodyLabelConstraint {
    UIScreen *mainScreen = [UIScreen mainScreen];
    CGFloat viewWidth = mainScreen.bounds.size.width;
    CGFloat bodyLabelWidth = viewWidth - 76 - 8;
    NSDictionary *metric = @ {
        @"bodyLabelWidth": [NSNumber numberWithFloat:bodyLabelWidth]
    };

    UILabel *bodyLabel = self.bodyLabel;
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[bodyLabel(bodyLabelWidth)]"
                                                                   options:0
                                                                   metrics:metric
                                                                     views:@ {
                                                                         @"bodyLabel": bodyLabel
                                                                     }];
    [self.contentView addConstraints:constraints];
}

【讨论】:

    【解决方案3】:

    在 Xcode 中,将最底部垂直约束的优先级设置为 750(或小于 1000 的任何值)。

    【讨论】:

    • @Tarek,请描述你的答案,我不明白你的意思。设置什么的优先级?
    • 只需在情节提要中选择约束,然后在对象检查器中设置其优先级字段。
    • 酷!将最底部垂直约束的优先级设置为 750 即可解决问题。
    【解决方案4】:

    可能是冲突的约束是因为前两个约束将标签的宽度定义为比单元格的宽度小 16pts,但第三个约束 UIView-Encapsulated-Layout-Width 想要使标签的大小不同.

    您可以尝试降低内容压缩阻力/拥抱属性的值,以允许标签忽略其固有大小。

    【讨论】:

    • 我试图修改那个值(降低水平拥抱优先级),但他们并没有真正解决我的问题。
    • 我也有同样的问题。你有没有找到解决这个问题的方法?真的很有帮助。
    猜你喜欢
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多