无法使用 uiimageview 同时满足 uitableviewcell 中的约束

Posted

技术标签:

【中文标题】无法使用 uiimageview 同时满足 uitableviewcell 中的约束【英文标题】:Unable to simultaneously satisfy constraints in uitableviewcell with uiimageview 【发布时间】:2015-07-22 13:51:23 【问题描述】:

首先,系统会自动删除适当的约束,因此一切都按预期工作,但我想了解如何使我的代码更好。 Uitableview 工作在 ios 8.0 自动模式下,没有实现 heightforindexpath 方法。

uitableview 在 uitableviewcells 中显示图像,我只是想向 uiimageview 添加比率约束,以便正确显示图像。似乎它按预期工作,但可能有一些我不明白的东西(我不确定在正确的时间没有给出调用方法的顺序或约束)。

以下是您可以查看的部分代码。图像的宽度和高度存储在数据库中,用于在下载图像之前设置约束。

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

PostImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierPostImage];

if (cell == nil) 
cell = [[PostImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierPostImage]; 

// Adding image         
[cell.imagePost setImageWithURL:[NSURL URLWithString:[[self.myData objectAtIndex:indexPath.row] valueForKey:@"image"]] placeholderImage:[UIImage imageNamed:@""]];
// Adding constraint    
[cell setConstraints:[[[self.myData objectAtIndex:indexPath.row] valueForKey:@"imageWidth"] doubleValue] withHeight:[[[self.myData objectAtIndex:indexPath.row] valueForKey:@"imageHeight"] doubleValue]];

return cell;

PostImageTableViewCell 自定义类的 setConstraints 方法在这里。我想要实现的是删除给前一个单元格的旧约束,并在下一个单元格中为新图像添加新约束......但根据我从日志中了解到的情况,它似乎没有这样做。是混合限制还是我必须给比率数字更清洁?

- (void)setConstraints:(double)width withHeight:(double)height 

    int fullWidth = [[UIScreen mainScreen] applicationFrame].size.width;

    [self.imagePost removeConstraint:self.imageConstraint];
    self.imageConstraint = [NSLayoutConstraint constraintWithItem:self.imagePost attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.imagePost attribute:NSLayoutAttributeHeight multiplier:(MAX(width,(fullWidth-20))/height) constant:0.0];
    [self.imagePost addConstraint:self.imageConstraint];

错误信息。似乎它不喜欢给定的比率约束......再次,它在模拟器/设备中正确显示,但我想了解我做错了什么。

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:0x7fb80cbac720 V:|-(11.5)-[CustLabelWithPadding:0x7fb80cb66240'JUL 20 - 18:39']   (Names: '|':UITableViewCellContentView:0x7fb80cb8bfd0 )>",
    "<NSLayoutConstraint:0x7fb80cbac7c0 V:[CustLabelWithPadding:0x7fb80cb66240'JUL 20 - 18:39'(23)]>",
    "<NSLayoutConstraint:0x7fb80cbac580 V:[CustLabelWithPadding:0x7fb80cb66240'JUL 20 - 18:39']-(11.5)-[CustLabelWithPadding:0x7fb80b90d8e0'Tr']>",
    "<NSLayoutConstraint:0x7fb80cbac8c0 V:[CustLabelWithPadding:0x7fb80b90d8e0'Tr'(>=34.5)]>",
    "<NSLayoutConstraint:0x7fb80cbac840 V:[CustLabelWithPadding:0x7fb80b90d8e0'Tr']-(1)-[CustLabelWithPadding:0x7fb80cba83e0'Rr']>",
    "<NSLayoutConstraint:0x7fb80cbac9e0 V:[CustLabelWithPadding:0x7fb80cba83e0'Rr'(>=34.5)]>",
    "<NSLayoutConstraint:0x7fb80cbac910 V:[CustLabelWithPadding:0x7fb80cba83e0'Rr']-(1)-[UIImageView:0x7fb80cba8a20]>",
    "<NSLayoutConstraint:0x7fb80cbaca30 V:[UIImageView:0x7fb80cba8a20]-(1)-[UIView:0x7fb80cba8c20]>",
    "<NSLayoutConstraint:0x7fb80cbacc00 V:[UIView:0x7fb80cba8c20(50.6)]>",
    "<NSLayoutConstraint:0x7fb80cbacb80 V:[UIView:0x7fb80cba8c20]-(11.5)-|   (Names: '|':UITableViewCellContentView:0x7fb80cb8bfd0 )>",
    "<NSLayoutConstraint:0x7fb80cbb0130 H:[UIImageView:0x7fb80cba8a20(352)]>",
    "<NSLayoutConstraint:0x7fb80cbb2080 UIImageView:0x7fb80cba8a20.width == 1.65647*UIImageView:0x7fb80cba8a20.height>",
    "<NSLayoutConstraint:0x7fb80cbabf60 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fb80cb8bfd0(392.5)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fb80cbb2080 UIImageView:0x7fb80cba8a20.width == 1.65647*UIImageView:0x7fb80cba8a20.height>

我稍微清理了代码,但基本上可用的宽度是 375-20*1.15。图像高度为 212.5(存储在数据库中的数字),因此最终比率将为 352/212.5 = 1.65647... 如错误消息所示。我认为另一个约束工作正常,因为它们用于没有图像的单元格,并且我没有错误消息。

【问题讨论】:

【参考方案1】:

实际上,如果您尝试进行数学运算,我们最终会丢失 0.1 ... 最小刻度为半点,系统最终无法找到相同的高度和。我用高度约束替换了比率约束,并确保我给出了正确的高度(没有“奇怪的数字”)

[self.contentView removeConstraints:self.imageConstraints];
double ratio = (MAX(width,(fullWidth-20*multiplier))/height);
double newHeight = floor((fullWidth / ratio) / 0.5 + 1) * 0.5;

NSDictionary *viewsDic = @@"imagePost":self.imagePost;
self.imageConstraints = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:[imagePost(%f)]",newHeight] options:0 metrics:0 views:viewsDic];
[self.contentView addConstraints:self.imageConstraints];

正如您所见,newHeight 已被修改,因此我们最终得到了一个系统会喜欢的“好”数字。这消除了我所有的约束问题。 50.6 的高度实际上也是一样的。使用相同的等式,我确保发送 51 而不是 50.6。

【讨论】:

以上是关于无法使用 uiimageview 同时满足 uitableviewcell 中的约束的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIView 中有一个 UIImageView 并应用 NSLayoutConstraint?

iOS 8 UITableViewCell 与 UIImageView 动态高度

无法同时满足约束 - 制图

使用代码创建约束 - 出现错误“无法同时满足约束”[重复]

iOS - AutoLayout'无法同时满足约束'

UITableViewCell - 无法同时满足约束