我有UITableView
self.tableView = [[UITableView alloc] init];
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 60.0f;
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:NSStringFromClass([MyTableViewCell class])];
带有自定义视图的自定义UITableViewCell
:
@implementation MyTableViewCell {
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupView];
}
return self;
}
- (void)setupView {
self.wrapperView = [UIView new];
[self.contentView addSubview:self.wrapperView];
self.firstView = [UIView new];
self.secondView = [UIView new];
}
- (void)prepareForReuse {
[super prepareForReuse];
[self.wrapperView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
- (void)updateConstraints {
[self.wrapperView mas_updateConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
UIView *previous;
for (NSUInteger index = 0; index < self.wrapperView.subviews.count; index++) {
UIView *subview = self.wrapperView.subviews[index];
[subview mas_makeConstraints:^(MASConstraintMaker *make) {
if (!previous) {
make.top.equalTo(self.wrapperView);
}
else {
make.top.equalTo(previous.mas_bottom);
}
make.left.equalTo(self.wrapperView);
make.right.equalTo(self.wrapperView);
make.height.equalTo(@50.0f);
if (index == self.wrapperView.subviews.count - 1) {
make.bottom.equalTo(self.wrapperView);
}
}];
previous = subview;
}
[super updateConstraints];
}
- (void)populate:(NSInteger)index {
[self.wrapperView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.wrapperView addSubview:self.firstView];
if (index % 2 == 0) {
[self.wrapperView addSubview:self.secondView];
}
[self updateConstraints];
}
@end
UITableViewDelegate
是这样实现的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = (MyTableViewCell *) [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([MyTableViewCell class])];
[cell populate:indexPath.row];
return cell;
}
正如你所看到的,我在展示secondView
和交替改变约束(使用砌体)以将wrapperView
边缘绑定到其子视图(以允许自我调整大小)时交替显示
问题是似乎UITableView
无法计算出重复使用细胞时的高度。当向下滚动单元格时,这会导致以下两个错误:
错误1 :(这里抱怨太多&#34;身高&#34;(50px),因为我们正在重复用于显示secondView
)的单元格
2015-10-19 09:52:54.075 SelfsizingTest[32296:1615907] 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)
(
"<MASLayoutConstraint:0x7fc5c3adaf40 UIView:0x7fc5c3ad9750.top == UITableViewCellContentView:0x7fc5c3ad8f30.top>",
"<MASLayoutConstraint:0x7fc5c3adb1c0 UIView:0x7fc5c3ad9750.bottom == UITableViewCellContentView:0x7fc5c3ad8f30.bottom>",
"<MASLayoutConstraint:0x7fc5c1543da0 UIView:0x7fc5c3ad9980.top == UIView:0x7fc5c3ad9750.top>",
"<MASLayoutConstraint:0x7fc5c15453c0 UIView:0x7fc5c3ad9980.bottom == UIView:0x7fc5c3ad9750.bottom>",
"<MASLayoutConstraint:0x7fc5c3c0d5d0 UIView:0x7fc5c3ad9980.height == 50>",
"<NSLayoutConstraint:0x7fc5c3ae2440 UITableViewCellContentView:0x7fc5c3ad8f30.height == 100>"
)
Will attempt to recover by breaking constraint
<MASLayoutConstraint:0x7fc5c3c0d5d0 UIView:0x7fc5c3ad9980.height == 50>
错误2 :(这里抱怨说不够,&#34;身高&#34;允许secondView
显示(缺少50像素))重复使用之前未显示secondView
2015-10-19 10:02:49.667 SelfsizingTest[32565:1625337] 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)
(
"<MASLayoutConstraint:0x7f9628420250 UIView:0x7f962841eb40.top == UITableViewCellContentView:0x7f962841b1e0.top>",
"<MASLayoutConstraint:0x7f96284204d0 UIView:0x7f962841eb40.bottom == UITableViewCellContentView:0x7f962841b1e0.bottom>",
"<MASLayoutConstraint:0x7f9628421560 UIView:0x7f962841ed70.height == 50>",
"<MASLayoutConstraint:0x7f9628628a70 UIView:0x7f962841ed70.top == UIView:0x7f962841eb40.top>",
"<MASLayoutConstraint:0x7f96286293e0 UIView:0x7f962841eef0.top == UIView:0x7f962841ed70.bottom>",
"<MASLayoutConstraint:0x7f9628629d80 UIView:0x7f962841eef0.height == 50>",
"<MASLayoutConstraint:0x7f9628629f00 UIView:0x7f962841eef0.bottom == UIView:0x7f962841eb40.bottom>",
"<NSLayoutConstraint:0x7f9628422490 UITableViewCellContentView:0x7f962841b1e0.height == 50>"
)
Will attempt to recover by breaking constraint
<MASLayoutConstraint:0x7f9628629d80 UIView:0x7f962841eef0.height == 50>
所以我的问题是,当细胞可以改变其子视图结构时,我如何使用自我调整大小的细胞?#34;细胞
我想解决这个问题的一种方法是为每个组合设一个单独的单元格,但在我的&#34;真实&#34;这会导致很多细胞。
我上传了一个示例项目,我重现了这个问题: https://www.dropbox.com/s/uyyzvxpkud7bcta/SelfsizingTest.zip?dl=0
答案 0 :(得分:0)
计算布局子视图中的高度,并将它们分配到实例变量中。计算将基于所需的数据和所涉及的子视图。
- (void)layoutSubviews {
[super layoutSubviews];
.....
self.heightEstimated = <some_variable_you_calulate_required_height_based_onSubview>;
}
然后创建一个虚拟单元格变量,仅用于计算高度
static MyCell *_mannequinCell;
现在只创建一个虚拟单元格
+ (MyCell *)mannequinCell {
if (!_mannequinCell) {
_mannequinCell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCellIdentifier"];
}
return _mannequinCell;
}
现在,每当您需要根据数据查找大小时,数据可能会因数据/子视图而变化。只需创建一个类似下面的方法。
+ (CGFloat)heightRequiredWithData:(Model *)data {
[[MyCell mannequinCell] populateCellWithData:data];
[[MyCell mannequinCell] layoutSubviews];
return [MyCell mannequinCell].heightEstimated;
}