简体   繁体   English

UITableViewCell:无法同时满足约束

[英]UITableViewCell: unable to simultaneously satisfy constraints

I've got a UITableViewCell that I'm creating, and I am using auto layout with constraints constructed entirely in code. 我有一个我正在创建的UITableViewCell ,我正在使用自动布局,其中约束完全由代码构成。

While the actual output in the app is fine (ie, it looks just as I have designed it to look), I am getting the famous "Unable to simultaneously satisfy constraints" error/warning message. 虽然应用程序中的实际输出很好(即,它看起来就像我设计的那样),但我得到着名的“无法同时满足约束”错误/警告消息。

Here is the list of constraints printed by the error message: 以下是错误消息打印的约束列表:

"<NSLayoutConstraint:0x7fb2f280e5e0 V:|-(0)-[UIScrollView:0x7fb2f0435730]   (Names: '|':UITableViewCellContentView:0x7fb2f04345c0 )>",
"<NSLayoutConstraint:0x7fb2f280e880 V:[UIScrollView:0x7fb2f0435730(280)]>",
"<NSLayoutConstraint:0x7fb2f280e630 V:[UIScrollView:0x7fb2f0435730]-(16)-[UIScrollView:0x7fb2f04360d0]>",
"<NSLayoutConstraint:0x7fb2f280e920 V:[UIScrollView:0x7fb2f04360d0(140)]>",
"<NSLayoutConstraint:0x7fb2f280e970 V:[UIScrollView:0x7fb2f04360d0]-(16)-[SummaryView:0x7fb2f0436c20]>",
"<NSLayoutConstraint:0x7fb2f280e9f0 V:[SummaryView:0x7fb2f0436c20(140)]>",
"<NSLayoutConstraint:0x7fb2f280e8d0 V:[SummaryView:0x7fb2f0436c20]-(0)-|   (Names: '|':UITableViewCellContentView:0x7fb2f04345c0 )>",
"<NSLayoutConstraint:0x7fb2f0439e30 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fb2f04345c0(44)]>"

Every single one of them is completely correct and exactly what I wanted except for the last one. 它们中的每一个都是完全正确的,正是我想要的,除了最后一个。 That one is quite clearly system generated. 系统生成的很明显。 44 points is (I believe) the system-standard cell height. 44分是(我相信)系统标准的单元格高度。 What's curious to me is that I have explicitly stated a correct cell height (in this case, 592 points). 对我来说很好奇的是我明确说明了正确的细胞高度(在这种情况下,592个点)。 Here is what I have done in my UITableViewController subclass: 这是我在UITableViewController子类中所做的:

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [TableViewCell heightNeededForCell];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [TableViewCell heightNeededForCell];
}

I think the reason this is happening is because of my cell's init function: 我认为发生这种情况的原因是因为我的单元格的init函数:

#pragma mark - Table View Cell Lifecycle
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self != nil) {
        [self setupUserInterface];
    }
    return self;
}

#pragma mark - UI Setup
- (void)setupUserInterface {
    [self createControls];
    [self createConstants];
    [self setupControls];
    [self layoutControls];
    [self.contentView layoutIfNeeded]; <-- Here's where the warning occurs
    // The UIScrollViews (which contain UIImageViews) were not
    // adjusting their contentSize properly, so I do it manually here
    self.scrollView1.contentSize = self.heartImageView1.bounds.size;
    self.scrollView2.contentSize = self.heartImageView2.bounds.size;
    }
}

From my results, it appears that I can safely ignore this error, but I'm kinda picky and don't like the fact that I'm getting a warning, even if I can explain it and it doesn't appear to cause any trouble. 根据我的结果,似乎我可以放心地忽略这个错误,但我有点挑剔而且不喜欢我收到警告的事实,即使我能解释它并且它似乎没有引起任何麻烦。 How would I successfully change the system-supplied constraint? 如何成功更改系统提供的约束?

You're right that the unexpected constraint is coming from the UITableView machinery itself. 你是对的,意外的约束来自UITableView机器本身。

I think when you call layoutIfNeeded in the initializer, you are confusing the UITableView machinery which expects to be responsible for doing layout on the cell as a whole, and for ensuring that the cell wraps its own contentView correctly. 我认为当您在初始化程序中调用layoutIfNeeded时,您会混淆UITableView机器,它希望负责在整个单元格上进行布局,并确保单元格正确包装其自己的contentView So you've told contentView to layout, but the cell itself has not been told to layout in tandem at the right time. 所以你已经告诉contentView布局,但是单元格本身并没有被告知在正确的时间串联布局。 What is the right time? 什么是合适的时间? Only UITableView knows its own secrets... 只有UITableView知道它自己的秘密......

There's probably more than one way to workaround the problem but what I'd suggest is to switch to using self-sizing cells. 可能有不止一种方法来解决这个问题,但我建议切换到使用自调整单元格。 That way you'd be taking responsibility for exactly what UITableView expects you to handle, leaving less room for surprises. 这样你就可以对UITableView希望你处理的内容负责,从而减少意外的空间。 Since you're already defining the cell's layout with Auto Layout, you're almost there already. 由于您已经使用自动布局定义了单元格的布局,因此您已经在那里了。

Here's how to do it: 这是怎么做的:

  1. Just add another layout constraint to the content view constraining it to your desired height of 592 points. 只需向内容视图添加另一个布局约束,将其约束到所需的592点高度。

  2. Then remove the delegate methods for tableView:estimatedHeightForRowAtIndexPath and tableView:heightForRowAtIndexPath entirely. 然后完全删除tableView:estimatedHeightForRowAtIndexPathtableView:heightForRowAtIndexPath的委托方法。

  3. Then set tableView.estimatedRowHeight = 600 (or any value, actually) in viewDidLoad . 然后在viewDidLoad设置tableView.estimatedRowHeight = 600 (或实际上的任何值)。

Now the tableView will set the cells to the height 592, which is the height that the cells themselves declare that they prefer via their own Auto Layout constraints. 现在tableView将单元格设置为高度592,这是单元格本身通过自己的自动布局约束声明的高度。

There are some examples of numerous ways to do this here: https://github.com/algal/TableViewSpike . 这里有很多方法可以做到这一点: https//github.com/algal/TableViewSpike

Note: Self-sizing cells requires a deployment target of iOS 8.0 or above. 注意:自行调整大小的单元需要iOS 8.0或更高版本的部署目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM