重用 tableviewcell 中的约束和高度未更新
Posted
技术标签:
【中文标题】重用 tableviewcell 中的约束和高度未更新【英文标题】:Reusing constraints in tableviewcell and height is not updated 【发布时间】:2016-05-27 04:48:43 【问题描述】:我有这样的表格视图单元格。
图像下载后,我更新图像视图的高度,使纵横比正确(宽度固定)。
[self.imgMain removeConstraint:self.aspectConstraint];
self.aspectConstraint = [NSLayoutConstraint constraintWithItem:self.imgMain
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.imgMain
attribute:NSLayoutAttributeHeight
multiplier:aspectRatioMult
constant:0];
self.aspectConstraint.priority = 999;//the reason is that if it is 1000, it violate with my label height constraints and it broke label constraint.So I set to 999
[self.imgMain addConstraint:self.aspectConstraint];
[self setNeedsUpdateConstraints];
[self updateConstraints];
问题是,虽然我更新了约束,但 tableviewcell 永远不会改变,它第一次在每 3 个单元格中重用单元格。如果我上下滚动,高度会更新。我该如何成功更新我的约束?
编辑
我这样设置单元格数据。
- (void)setData:(NSDictionary *)dict
if (!dict)
return;
self.cellData = [NSDictionary dictionaryWithDictionary:dict];
[self.imgMain setImageWithURL:[NSURL URLWithString:self.cellData[SERVER_IMG]] placeholderImage:[UIImage new] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL)
if (image)
[self putImage:image];
return ;
[self putImage:[UIImage imageNamed:@"placeholder.png"]];
usingActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
NSString *name = [NSString stringWithFormat:@"%@%@",SERVER_NAME, [LocalizationHelper getExtForLocale]];
if([self.cellData[SERVER_INTEGRATION_ID]intValue]==SERVER_ISHOPCHANGI_ID)
[self.lblShopName setText:self.cellData[SERVER_DESCRIPTION]];
[self.btnMap setHidden:YES];
self.imgWidthMapBtnConstraint.constant = 0;
else
[self.lblShopName setText:self.cellData[SERVER_LOCATIONS][0][SERVER_SHOP]];
[self.btnMap setHidden:[Helper isPointZero:dict[SERVER_LOCATIONS][0]]];
self.imgWidthMapBtnConstraint.constant = 33;
[self.lblOfferTitle setText:self.cellData[name]];
【问题讨论】:
[self layoutIfNeeded] 丢失 如果我放 layoutIfNeeded 则它不起作用。 @PKT 【参考方案1】:让事情变得清晰的小概述:
在使用 Autolayout 时,为了计算单元格的高度,ios 仅在第一次为 indexPath 加载单元格时计算高度并缓存它,并在下次重用时,单元格再次可见。
解决 - >
任意使用,
tableView.beginUpdates()
tableView.endUpdates()
OR
tableView.reloadRowsAtIndexPath
参考链接
How to animate UITableViewCell height using auto-layout?
https://blog.pivotal.io/labs/labs/expandable-uitableviewcells
回答您的问题
您可以在 set Data like 中使用 tableView.beginUpdates()/endUpdates()
以下不会导致无限循环
-(void)setData
/*YOUR CODE UPDATING THE CONSTRAINTS*/
tableView.beginUpdates()
tableView.endUpdates()
或
使用 reloadRows CHECK 如果 CONSTRAINTS 已经设置,则中断循环,如果是,则不要调用 reloadRows*
-(void)setData
CGFloat requiredValue = 0;
if([self.cellData[SERVER_INTEGRATION_ID]intValue]==SERVER_ISHOPCHANGI_ID)
requiredValue = 0;
else
requiredValue = 33;
/*CHECK IF CONSTRAINT ALREADY SET*/
if(self.imgWidthMapBtnConstraint.constant != requiredValue)
self.imgWidthMapBtnConstraint.constant = requiredValue;
/**RELOAD ROW*/
【讨论】:
我正在更改我的 tableviewcell 中的约束。我是否需要与代表一起发回重新加载表? 是的,您必须使用委托获取您的 tableview 参考。 谢谢。我已经在我的问题中设置了数据。我什么时候应该调用 reloadRows?我尝试调用 setdata。然后,当我滚动单元格时,我设置数据,我再次重新加载并导致再次设置数据等等。 嗯...我认为它仍然是无限的。我仍然有这样的错误。 imgur.com/8zlcxm2 不过我使用的是动态高度。 if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) return UITableViewAutomaticDimension; 你试过 tableView.beginUpdates()/endUpdates() 吗??【参考方案2】:斯威夫特
是的,更改约束不会做任何事情,因为在调用 heightForRowAtIndexPath
时已经计算了高度,并且仅在重新加载 tableView
或重新加载 cell
时才会调用。
您可以调用 tableView.reloadData() 但如果您只在一个单元格中进行更改,则效率不高。
如果您知道更改的单元格的 indexPath,只需调用 tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
【讨论】:
我应该在哪里/何时调用/放置 reloadRowsAtIndexPaths? 你应该先获取对应单元格的indexPath。然后,在 setImageWithURL 的完成块中调用 reloadRowsAtIndexPath。【参考方案3】:想象 UITableViewCell 只有一个标签,它的高度是 AutomaticDimension, 有时我希望保证金取决于数据
一开始我是这样设置约束的
[_label mas_makeConstraints:^(MASConstraintMaker *make)
make.left.equalTo(@(0));
make.right.equalTo(@(0));
make.top.equalTo(@(self.margin));
make.height.equalTo(@30)
make.bottom.equalTo(@(-self.margin));
];
我想在单元格数据更改时更改边距
- (void)setMargin:(CGFloat)margin
_margin = margin;
[self.label mas_updateConstraints:^(MASConstraintMaker *make)
make.top.equalTo(@(self.margin));
make.bottom.equalTo(@(-self.margin));
];
滚动 UITableview ,当我更改此单元格的边距时 xcode 警告(重用)
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:0x1c42b9e60 UILabel:0x13fec3bb0.top == UITableViewCellContentView:0x13fe9ef60.top + 10>",
"<MASLayoutConstraint:0x1c42b9d40 UILabel:0x13fec3bb0.height == 30>",
"<MASLayoutConstraint:0x1c42b9e00 UILabel:0x13fec3bb0.bottom == UITableViewCellContentView:0x13fe9ef60.bottom - 10>",
"<NSAutoresizingMaskLayoutConstraint:0x1c0291710 UITableViewCellContentView:0x13fe9ef60.height == 80>"
)
Will attempt to recover by breaking constraint
<MASLayoutConstraint:0x1c42b9d40 UILabel:0x13fec3bb0.height == 30>
为避免此警告设置了优先级:
[_label mas_makeConstraints:^(MASConstraintMaker *make)
make.left.equalTo(@(0));
make.right.equalTo(@(0));
make.top.equalTo(@(self.margin));
make.height.equalTo(@30).priority(MASLayoutPriorityDefaultMedium);
make.bottom.equalTo(@(-self.margin));
];
【讨论】:
以上是关于重用 tableviewcell 中的约束和高度未更新的主要内容,如果未能解决你的问题,请参考以下文章
UIImageView 不是 StackView 和 TableViewCell 中的自动高度
动态增加 UILabel & TableView Cell 的高度?
关于单元重用的自定义 UITableViewCell 约束问题