Ios UITableViewCell:无法同时满足约束

Ios UITableViewCell:无法同时满足约束,ios,objective-c,uitableview,autolayout,Ios,Objective C,Uitableview,Autolayout,我正在创建一个UITableViewCell,我使用的是完全用代码构造的约束的自动布局 虽然应用程序中的实际输出很好,也就是说,它看起来就像我设计的那样,但我收到了著名的“无法同时满足约束”错误/警告消息 以下是错误消息打印的约束列表: "<NSLayoutConstraint:0x7fb2f280e5e0 V:|-(0)-[UIScrollView:0x7fb2f0435730] (Names: '|':UITableViewCellContentView:0x7fb2f04345c

我正在创建一个UITableViewCell,我使用的是完全用代码构造的约束的自动布局

虽然应用程序中的实际输出很好,也就是说,它看起来就像我设计的那样,但我收到了著名的“无法同时满足约束”错误/警告消息

以下是错误消息打印的约束列表:

"<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)]>"
我认为发生这种情况的原因是因为我的单元格的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;
    }
}

从我的结果来看,似乎我可以安全地忽略这个错误,但我有点挑剔,不喜欢收到警告的事实,即使我可以解释它,而且它似乎不会引起任何麻烦。如何成功更改系统提供的约束?

您是对的,意外约束来自UITableView机器本身

我认为,当您在初始值设定项中调用layoutifneedd时,您混淆了UITableView机制,它将负责在整个单元格上进行布局,并确保单元格正确包装自己的contentView。您已经告诉contentView进行布局,但是没有告诉单元格本身在正确的时间进行串联布局。什么时候合适?只有UITableView知道自己的秘密

解决这个问题的方法可能不止一种,但我的建议是改用自调整大小的单元格。这样,您就可以对UITableView期望您处理的事情负起责任,从而减少意外发生的空间。因为您已经用自动布局定义了单元的布局,所以您几乎已经做到了

以下是如何做到这一点:

只需向内容视图添加另一个布局约束,将其约束到所需的592点高度即可

然后完全删除tableView:EstimatedHeightForRowatineXpath和tableView:HeightForRowatineXpath的委托方法

然后设置tableView.estimatedRowHeight=600或任何值,实际上在viewDidLoad中

现在,tableView将单元格设置为高度592,这是单元格本身通过自身的自动布局约束声明的首选高度

这里有许多这样做的方法的例子:


注意:自调整单元格大小需要iOS 8.0或更高版本的部署目标。

您是对的,意外约束来自UITableView机器本身

我认为,当您在初始值设定项中调用layoutifneedd时,您混淆了UITableView机制,它将负责在整个单元格上进行布局,并确保单元格正确包装自己的contentView。您已经告诉contentView进行布局,但是没有告诉单元格本身在正确的时间进行串联布局。什么时候合适?只有UITableView知道自己的秘密

解决这个问题的方法可能不止一种,但我的建议是改用自调整大小的单元格。这样,您就可以对UITableView期望您处理的事情负起责任,从而减少意外发生的空间。因为您已经用自动布局定义了单元的布局,所以您几乎已经做到了

以下是如何做到这一点:

只需向内容视图添加另一个布局约束,将其约束到所需的592点高度即可

然后完全删除tableView:EstimatedHeightForRowatineXpath和tableView:HeightForRowatineXpath的委托方法

然后设置tableView.estimatedRowHeight=600或任何值,实际上在viewDidLoad中

现在,tableView将单元格设置为高度592,这是单元格本身通过自身的自动布局约束声明的首选高度

这里有许多这样做的方法的例子:


注意:自调整单元格大小要求部署目标为iOS 8.0或更高版本。

谢谢您的回答。在需要我为estimatedRowHeight输入一个假值时,为了封装单元本身内部的高度大小而绕过提供的协议方法对我来说是没有意义的。相反,因为我的问题与UIScrollView和UIImageView大小调整和内容大小调整有关,所以我将代码移动到另一个方法中,在tableView中获取单元格后调用该方法:cellForRowAtIndexPath:。我承认这不是最优雅的,但它现在工作正常,我的登录仍然是按需要划分的。我不是建议你规避任何东西或使用假值!我建议的是使用API的官方的、有文档记录的方法。也就是说,如果单元定义了足够的自动布局约束来定义其自身的高度,那么将estimatedRowHeight设置为任何非零值就是告诉UITableView您希望它使用自动布局来计算单元高度的方式。这在WWDC 2014《表和集合视图的新增功能》中有解释。事实上,在那篇演讲中,苹果
介绍自动上浆机的目的是为了避免人们使用您在评论中描述的手动上浆,如果我理解正确的话。反语的我将看一看那个视频,但我觉得奇怪的是,任何非零值对布局都有相同的影响。每个设备的单元格高度都会发生变化,因此设置一个静态值来表示自动调整大小似乎会误导我。相反,如果我使用我的计算设置该值,那么我实际上只是将完全相同的代码从协议方法移动到了,比如说,viewDidLoad。顺便说一下,即使我完全尝试了你的方法,我仍然有同样的问题,因为分隔符仍然会导致奇怪的0.5分问题。关闭分隔符修复了这一问题,但这不是我想要的。再次,我将观看视频,但将显式布局代码移动到另一个我从tableView调用的方法:CellForRowatineXpath:解决了我的问题,并且没有引入我在前面的评论中提到的奇怪之处。我并不是在反驳你的断言,即苹果公司的做法是正确的;我的观点是,除非有一个布尔值,比如tableView.cellsUseAutolayout=YES;,否则;,坚持旧方法对我来说更有意义。不过,谢谢你给了我学习的机会-谢谢你的回答。在需要我为estimatedRowHeight输入一个假值时,为了封装单元本身内部的高度大小而绕过提供的协议方法对我来说是没有意义的。相反,因为我的问题与UIScrollView和UIImageView大小调整和内容大小调整有关,所以我将代码移动到另一个方法中,在tableView中获取单元格后调用该方法:cellForRowAtIndexPath:。我承认这不是最优雅的,但它现在工作正常,我的登录仍然是按需要划分的。我不是建议你规避任何东西或使用假值!我建议的是使用API的官方的、有文档记录的方法。也就是说,如果单元定义了足够的自动布局约束来定义其自身的高度,那么将estimatedRowHeight设置为任何非零值就是告诉UITableView您希望它使用自动布局来计算单元高度的方式。这一点在WWDC 2014《表和集合视图的新功能》中有解释。事实上,在那次演讲中,苹果推出自动上浆机的全部原因是,如果我理解正确的话,可以避免人们使用您在评论中描述的手动上浆。反语的我将看一看那个视频,但我觉得奇怪的是,任何非零值对布局都有相同的影响。每个设备的单元格高度都会发生变化,因此设置一个静态值来表示自动调整大小似乎会误导我。相反,如果我使用我的计算设置该值,那么我实际上只是将完全相同的代码从协议方法移动到了,比如说,viewDidLoad。顺便说一下,即使我完全尝试了你的方法,我仍然有同样的问题,因为分隔符仍然会导致奇怪的0.5分问题。关闭分隔符修复了这一问题,但这不是我想要的。再次,我将观看视频,但将显式布局代码移动到另一个我从tableView调用的方法:CellForRowatineXpath:解决了我的问题,并且没有引入我在前面的评论中提到的奇怪之处。我并不是在反驳你的断言,即苹果公司的做法是正确的;我的观点是,除非有一个布尔值,比如tableView.cellsUseAutolayout=YES;,否则;,坚持旧方法对我来说更有意义。不过,谢谢你给了我学习的机会-
#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;
    }
}