iOS 8具有可变高度的自调整大小单元格

iOS 8具有可变高度的自调整大小单元格,ios,objective-c,uitableview,uikit,Ios,Objective C,Uitableview,Uikit,我使用创建了一个具有自调整大小的UITableViewCells的tableview tableview.rowHeight=UITableViewAutomaticDimension 对于测试,创建了一个UIView,并使用以下约束将其添加到cell.contentView。(使用砖石) 选择行时,我希望更改所选单元格的高度。我通过以下方式做到这一点: - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super

我使用创建了一个具有自调整大小的UITableViewCells的tableview

tableview.rowHeight=UITableViewAutomaticDimension

对于测试,创建了一个
UIView
,并使用以下约束将其添加到
cell.contentView
。(使用砖石)

选择行时,我希望更改所选单元格的高度。我通过以下方式做到这一点:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    [self.testView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (selected) {
            make.height.equalTo(@100);
        }
        else {
            make.height.equalTo(@10);
        }
    }];

    [UIView animateWithDuration:0.3f animations:^{
        [super layoutIfNeeded];
    }];
}
它似乎可以工作,但xcode出现以下错误:

无法同时满足约束。

然后,问题是
contentView
正在自己创建高度约束(因为
contentView.translatesAutoResistingGMaskintoConstraints=YES;

因此,当第一次运行updateConstraint时,系统将在
contentView
上创建一个等于
10.0f

之后,当调用
setSelected…
时,我会更改
testView
的高度,因此
testView.height
(100.0f)和
contentView.height
(10.0f)之间存在冲突,因为
testView
附在
contentView
的底部(以便自调整单元格大小)它给出了错误的答案

我试着设置
contentView.translatesAutoResizezingMaskintoConstraints=NO
但是UtableViewCell似乎无法为单元格找到合适的大小。(有时它太宽/太小)等等


实现可动态改变高度的自调整单元格大小的正确方法是什么?

这里有两个问题:

1。自动布局消息:
无法同时满足约束。

这是因为您更新了自定义视图的
高度
约束,但未更新
内容视图的
高度
约束。由于您还将自定义视图的
bottom
约束设置为contentView
bottom
,因此系统无法同时满足这两个约束:自定义视图的高度不能为100,同时连接到contentView的底部,而contentView的高度仍然为10

解决这个问题相当容易。可以为contentView定义高度约束,并将其设置为自定义视图的高度:

[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(self.testView);
}];
这就解决了问题

2。更新单元格的高度

更新单元格高度并不容易,因为单元格高度是由
UITableViewController
处理的,而不是单元格本身。当然,您可以更改单元格的高度,但只要
UITableViewController
没有给单元格足够的空间,您就看不到新的单元格高度。您将看到现在较高的单元格将与下一个单元格重叠

因此,您需要一种方法来告诉
UITableViewController
它应该更新单元格的高度。您可以通过调用
reloadRowsAtIndexPaths:withRowAnimation:
来实现这一点。这将重新加载单元格,并使其具有良好的动画效果。因此,单元格必须在
UITableViewController
上调用该方法。这里的挑战是:
UITableViewCell
没有引用它的
UITableViewController
(它应该没有)

您可以做的是子类
UITableViewCell
,并为其提供一个closure属性,它可以在其高度发生变化时执行该属性:

class DynamicHeightTableViewCell: UITableViewCell {
    var heightDidChange: (() -> Void)?
    ...
现在,当您在
UITableViewControllerDataSource
中将某个单元格出列时,您可以设置其关闭:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("DynamicHeightTableViewCell", forIndexPath: indexPath)
    if let customCell = cell as? DynamicHeightTableViewCell {
        customCell.heightDidChange = { [weak cell, weak tableView] in
            if let currentIndexPath = tableView?.indexPathForCell(cell!) {
                tableView?.reloadRowsAtIndexPaths([currentIndexPath], withRowAnimation: .Automatic)
            }
        }
    }

    return cell
}
然后,当单元改变其高度时,您只需执行闭包,单元就会重新加载:

func theFunctionWhereTheHeightChanges() {

   // change the height

   heightDidChange?()
}

您是否设置了
estimatedRowHeight
属性?我没有设置estimatedRowHeight:),但只是进行了测试,它对高度约束冲突的问题没有任何影响。对我不起作用(重新加载RowsatindExpaths时可能会发生崩溃)将testView链接到contentView的约束也会触发自动布局冲突。
func theFunctionWhereTheHeightChanges() {

   // change the height

   heightDidChange?()
}