UITableViewCell中iOS7上的自动布局约束问题

Ale*_*xis 104 uitableview ios autolayout nslayoutconstraint ios7

我正在以编程方式使用自动布局约束来布局我的自定义UITableView单元格,并且我正确地定义了单元格大小 tableView:heightForRowAtIndexPath:

它在iOS6上运行得很好,在iOS7中看起来也很好

但是当我在iOS7上运行应用程序时,这是我在控制台中看到的那种消息:

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] 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:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50]   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
        "<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
        "<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
        "<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-|   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>
Run Code Online (Sandbox Code Playgroud)

而且的确有在该列表中,我不想约束之一:

"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
Run Code Online (Sandbox Code Playgroud)

并且我无法将translatesAutoresizingMaskIntoConstraints属性设置contentView为NO =>它会弄乱整个单元格.

44是默认的单元格高度,但我在表视图委托中定义了我的自定义高度,为什么单元格contentView有这个约束?什么可能导致这个?

在iOS6中它没有发生,iOS6和iOS7上的一切看起来都很好.

我的代码非常大,所以我不会在这里发布,但如果你需要,可以随意问一个pastebin.

在细胞初始化中指定我是如何做到的:

  • 我创建了所有标签,按钮等
  • 我把他们的translatesAutoresizingMaskIntoConstraints财产设置为NO
  • 我将它们添加为contentView单元格的子视图
  • 我在上面添加了约束 contentView

我也非常有兴趣了解为什么这只发生在iOS7上.

lia*_*ols 132

我也有这个问题..看起来,在layoutSubviews调用之前,contentView的框架不会更新, 但是单元格的框架会更早更新,而在{0, 0, 320, 44}评估约束时将contentView的框架设置为.

在更详细地查看contentView之后,似乎不再设置autoresizingMasks.

在约束视图之前设置autoresizingMask可以解决此问题:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self)
    {
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
        [self loadViews];
        [self constrainViews];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

  • @ L14M333见我张贴在这个[评论点击这里]代码(https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188) - 基本上,你应该只能够设置`self.contentView. bounds = CGRectMake(0,0,99999,99999);`在添加约束之前,应该解决问题. (11认同)
  • autoresizingMask对我不起作用:初始约束消失了但是新增了3个"<NSAutoresizingMaskLayoutConstraint:0x8b79740 h = - & - v = - & - UITableViewCellContentView:0x8b44010.height == UITableViewCellScrollView:0x8b4a130.height>", "<NSAutoresizingMaskLayoutConstraint:0x8b7b9f0 h = - & - v = - & - UITableViewCellScrollView:0x8b4a130.height == LibraryCell:0x8ac19d0.height>","<NSAutoresizingMaskLayoutConstraint:0x8b7c590 h = - &v = - &V:[LibraryCell: 0x8ac19d0(0)]>" (2认同)
  • 在摆脱其他自动布局问题(iOS 7/iOS 8)后,我发现使用`self.contentView.bounds = CGRectMake(0,0,99999,99999);`就像使用`self.contentView.autoresizingMask一样好= UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;`.在将约束添加到我的内容视图之前,我将其放入`updateConstraints`中. (2认同)

KoC*_*BTa 35

显然,使用iOS 8 SDK的iOS 7上的UITableViewCell和UICollectionViewCell有问题.

您可以在重复使用单元格时更新单元格的contentView,如下所示:

对于Static UITableViewController:

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }

    //your code goes here

    return cell;
}

#endif
#endif
Run Code Online (Sandbox Code Playgroud)

由于静态表视图控制器很脆弱,如果你实现了一些数据源或deletegate方法,很容易被破坏 - 有一些检查可以确保这些代码只能在iOS 7上编译和运行

它与标准动态UITableViewController类似:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"CellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }
    //your code goes here       
    return cell;
}
Run Code Online (Sandbox Code Playgroud)

对于这种情况,我们不需要编译额外检查,因为需要实现此方法.

对于这两种情况和UICollectionViewCell,这个想法都是一样的,就像在这个帖子中评论的那样:在仅在iOS 7上运行时,在Storyboard原型单元(Xcode 6,iOS 8 SDK)中自动调整UICollectionViewCell contentView框架的问题.


Ste*_*ven 13

由于细胞正在重复使用,并且高度可以根据内容而改变,我认为通常最好将间距的优先级设置为低于要求.

在您的情况下,UIImageView与顶部的间距为15,底部视图与底部的间距为0.如果将这些约束的优先级设置为999(而不是1000),则应用程序不会崩溃,因为不需要约束.

调用layoutSubviews方法后,单元格将具有正确的高度,并且可以正常满足约束.


asd*_*ads 9

我仍然没有为故事板找到一个好的解决方案......有些信息也在这里:https: //github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188

根据他们的建议:

self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);
Run Code Online (Sandbox Code Playgroud)

我引出了我的解决方案:

  • 右键单击故事板
  • 打开为 - >源代码
  • 在那里搜索字符串"44"
  • 它会是这样的

.

<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
        <rect key="frame" x="0.0" y="22" width="320" height="44"/>
Run Code Online (Sandbox Code Playgroud)

.

  • 用rowHeight ="9999"替换rowHeight ="44",用height ="9999"替换height ="44"
  • 右键单击故事板
  • 打开为 - >界面生成器
  • 运行您的应用程序并检查输出