在iOS 8中自动调整UITableViewCell的大小

在iOS 8中自动调整UITableViewCell的大小,ios,objective-c,uitableview,autolayout,Ios,Objective C,Uitableview,Autolayout,我有一个UITableViewCell子类,它包含一个多行标签,我希望单元格根据标签的内容动态调整大小。我知道iOS 8引入了基于自动布局约束的自动调整单元格大小的功能,我已经找到了几个这样的例子,但是我仍然在正确实现这种功能时遇到了一些问题 以下是我的updateConstraints实现: - (void)updateConstraints { [super updateConstraints]; [self addConstraints:[NSLayoutConstrai

我有一个UITableViewCell子类,它包含一个多行标签,我希望单元格根据标签的内容动态调整大小。我知道iOS 8引入了基于自动布局约束的自动调整单元格大小的功能,我已经找到了几个这样的例子,但是我仍然在正确实现这种功能时遇到了一些问题

以下是我的updateConstraints实现:

- (void)updateConstraints {
    [super updateConstraints];

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_nameLabel(==20)]-10-[_tweetLabel]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_nameLabel, _tweetLabel)]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_avatarView]-10-[_nameLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView, _nameLabel)]];

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_nameLabel]-10-[_tweetLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_nameLabel, _tweetLabel)]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_avatarView]-10-[_tweetLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView, _tweetLabel)]];

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_avatarView(==45)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView)]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_avatarView(==45)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView)]];
}
在表视图控制器中,我将行高度设置为UITableViewAutomaticDimension(并且还设置了估计的行高度)。在运行时,我遇到一系列自动布局错误,所有表视图单元格几乎完全重叠

自动布局冲突发生在以下约束之间:

  • V:|-(10)-[\u名称标签]
  • V:[\u名称标签(20)]
  • V:[\u namelab]-(10)-[\u tweetlab]
  • V:[\u tweetLabel]-(10)-|
  • V:[单元格(44)]

我怀疑最后一个约束“UIView封装布局高度”(强制高度为44)是问题的原因,但我不太确定这是从哪里来的,因此希望有人能对此问题有所了解。

您确定已将单元格上的-translatesAutoReshizingMacSkintoConstraints设置为否?如果不这样做,系统会根据自动调整大小掩码生成约束,这是以前在iOS上进行布局的方法,在使用自动布局时应该禁用。

我刚刚遇到这个问题

从许多其他Stackoverflow帖子中,他们推荐:

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
一开始这对我不起作用。我发现我还需要做

self.frame = CGRectMake(0, 0, self.frame.size.width, 50);
我的自定义单元格的init方法与他的类似:

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if(self)
    {
        [self initViews];
        [self initConstraints];
    }

    return self;
}
我将代码放在我的“initViews”方法中:

问题解决了,我的手机看起来也正常


这对您有用吗?

为了实现表格视图单元格的自动行高,您需要执行以下操作:

  • 在单元的contentView中实现自动布局约束,允许视图表达其首选高度。确保将
    UILabel
    s设置为多行换行

    确保已在两个标注中定义了约束的轴向链,即从视图的一条边到另一条边的所有约束。确保这些约束正确的最简单方法可能是将自定义内容实现为一个普通的旧
    UIView
    (易于测试),然后使用约束,以便
    UITableViewCell.contentView
    包含该视图。(我用于自动构建“视图包装单元”。)

  • 设置
    tableView.rowHeight=UITableViewAutomaticDimension

  • 设置
    tableView.estimatedRowHeight=400
    或其他合理的慷慨值,以便在估值过低时解决某些UIKit错误

  • 我花了大量令人费解的时间来处理这个特性。显示了七个完整的自调整大小的表格视图单元格示例,其中包含一个包装文本标签——编程、基于笔尖、基于情节提要等

    最后,如果在第一次加载表视图时看到关于不可满足约束的警告,并提到“UIView封装布局高度”或类似内容,则不要太担心。这是
    UITableView
    创建单元格、根据自动布局约束确定其大小以及保持
    UITableViewCell
    紧密包裹其
    contentView
    的初始过程的产物。我上面提到的repo有更广泛的讨论和代码,用于探索API中这个有点尴尬的角落


    如果约束冲突警告在单元格加载并滚动一段时间后仍然存在,或者最初看到的布局不正确,则只需担心这些警告。在这种情况下,第一步应该始终是通过开发约束并在可能的情况下在普通的
    UIView

    中单独测试它们来确保约束是正确的。您是否检查了在UITableViewCell上是否将TranslatesAutorezingMaskinToConstraints设置为NO,谢谢你的建议,但是现在一个大的灰色矩形占据了大部分屏幕(Xcode的视图显示它有数百个单元格分隔符)。我肯定在委托方法中给出了正确的单元格数,知道为什么会发生这种情况吗?不确定这是否是Apple autolayout的错误,但本文中的用户建议:我也得到了与我自己的动态tableviewcell高度约束冲突相同的(44)单元格高度。它似乎只出现在iOS 8中,iOS 7正在运行。奇怪的是,如果你的所有细胞都是相同的高度,而你没有做动态细胞高度,那么就没有这个问题。我真的希望这是一个Apple bug>(注意:我使用的是iOS 8之前的动态单元格高度代码)谢谢你指出,我确实为单元格的子视图设置了,但不是为单元格本身设置了。但是当我在单元格上设置它时,发生了一件有趣的事情-一个灰色矩形现在占据了大部分屏幕,根据Xcode的视图检查,它有成百上千的表视图分隔符,你知道是什么原因造成的吗?我在委托回调中返回了正确的行数,因此不确定原因是什么。不知道这是否有帮助,但Apple的“updateConstraints”文档明确指出,“[super updateConstraints]”应作为实现的最后一步调用。谢谢!在我的例子中,视图看起来不错,但不知何故,我得到了很多警告。我按照你的建议加上了面具和镜框。我想问题是默认高度44太小,无法容纳我的视图,即使在显示时高度会拉伸,内部布局管理器还是会抱怨。我至少需要200,所以我设置了一个安全帧(0,0,
    -(void)initViews
    {
        ...
    
        // fixes an iOS 8 issue with UIViewEncapsulated height 44 bug
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        self.frame = CGRectMake(0, 0, self.frame.size.width, 50);
    }