I have a simple demo AutoSizing UITableView project like this : when you tap the tableview cells will make cell's red subview ‘s height constraint to bigger value(from original 60 to 100) and calling reloadData.
#import "ViewController.h"
#import "TestCell.h"
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic,assign) NSInteger value;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView.dataSource = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.delegate = self;
[self.tableView registerNib:[UINib nibWithNibName:@"TestCell" bundle:nil] forCellReuseIdentifier:@"TestCell"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestCell* cell = (TestCell*)[tableView dequeueReusableCellWithIdentifier:@"TestCell" forIndexPath:indexPath];
cell.value = self.value;
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.value += 1;
[self.tableView reloadData];
}
and the cell:
#import "TestCell.h"
@interface TestCell()
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightConstraint;//red view's height constraint
@end
@implementation TestCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)setValue:(NSInteger)value
{
if (value > 1)
{
self.heightConstraint.constant = 100;
}
[self setNeedsLayout];
[self setNeedsUpdateConstraints];
}
@end
And the cell's xib is containing just one subview in it:
But when I invoke the reloadData, there will be a constraints break warning like this
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.
(
"<NSLayoutConstraint:0x6000021279d0 UIView:0x10d615680.height == 100 (active)>",
"<NSLayoutConstraint:0x600002126f80 V:[UIView:0x10d615680]-(10)-| (active, names: '|':UITableViewCellContentView:0x10d6154c0 )>",
"<NSLayoutConstraint:0x600002127070 V:|-(0)-[UIView:0x10d615680] (active, names: '|':UITableViewCellContentView:0x10d6154c0 )>",
"<NSLayoutConstraint:0x6000021277a0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x10d6154c0.height == 70 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000021279d0 UIView:0x10d615680.height == 100 (active)>
There is a UIView-Encapsulated-Layout-Height constraint here , I think this constraint is generated by the layout system at the first layout .
If I call the reloadData afterwise, The layout will still use that cell height constraint genereated before (height:70), so If I change the subview's height to 100 , This will make a conflict .
I think the height constraint generated by system should be invalid at sometime . Is there anyway to do this?
When a table view lays out its cells, the cells inherit a height constraint. If you do something to change the cell's views constraints (such as changing the red view's height constant), there will be an auto-layout conflict until the next layout pass.
Assuming your redView
has a bottom constraint to the bottom of the cell's contentView
...
Change the Priority
of that bottom constraint to 999
. That will get rid of the auto-layout complaints.
Side note -- these lines are not needed:
[self setNeedsLayout];
[self setNeedsUpdateConstraints];