I have a UITableView, with a header defined in UIBuilder. I was running into errors with autoresizing masks conflicting with my constraints, so I started poking around until I found the cause.
Unfortunately, fixing what appears to be the cause is causing a crash. When I programmatically turn off setTranslatesResizingMasks, the conflicting layout error doesn't occur (either because it's fixed, or because it never gets the chance to) and instead I get a crash:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'
I tried the suggestion from some other threads (like this one) about using method swizzling to 'patch' UITableViewCell (and I went ahead and did UITableVIew while I was at it), but it didn't help.
Edit:
Here's some sample code that can make it. Because I need to be able to mutate the view at run time, it has to be created via code, not storyboard.
Please note that if I add the table header in as it's own view, everything works fine; it's when I try to embed it as the table's header view that things start to blow up. I either turn the tableHeader view's translateAutoresizingMaskIntoConstraints off to avoid conflicts, or I get conflicts with my use of autolayout (the constraints it breaks cause some of my controls to mysteriously vanish).
self.palletTagField=[[UITextField alloc] init];
[self.palletTagField setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.palletTagField setDelegate:self];
[self.palletTagField setBorderStyle:UITextBorderStyleRoundedRect];
UIButton *addButton=[UIButton buttonWithType:UIButtonTypeContactAdd];
[addButton addTarget:self
action:@selector(addPalletTagButtonPressed)
forControlEvents:UIControlEventTouchUpInside];
[addButton setTranslatesAutoresizingMaskIntoConstraints:NO];
UIView *tableHeader=[[UIView alloc] init];
[tableHeader setTranslatesAutoresizingMaskIntoConstraints:NO];//Problem line
[tableHeader addSubview:self.palletTagField];
[tableHeader addSubview:addButton];
[tableHeader addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[field]-[button]-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:@{@"field":self.palletTagField,
@"button":addButton}]];
[tableHeader addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[field]-|"
options:kNilOptions
metrics:nil
views:@{@"field": self.palletTagField}]];
UITableView *palletTable=[[UITableView alloc] init];
[palletTable registerClass:[UITableViewCell class] forCellReuseIdentifier:@"palletTagCell"];
[palletTable setEditing:YES];
self.palletTagTable=palletTable;
palletTable.tableHeaderView=tableHeader;
[palletTable setTranslatesAutoresizingMaskIntoConstraints:NO];
[palletTable setDataSource:self];
[palletTable setDelegate:self];
[self.contentView addSubview:palletTable];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[pallets]-|"
options:kNilOptions
metrics:nil
views:@{@"pallets":palletTable}]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[last]-[pallets(>=400)]"
options:kNilOptions
metrics:nil
views:@{@"last": lastObject,
@"pallets":palletTable}]];
Sample output from debugger:
[ANONYMIZED][31422:70b] 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)
(
"<NSLayoutConstraint:0x8f77810 H:|-(NSSpace(20))-[UITextField:0x8f6ad70] (Names: '|':UIView:0x8f77650 )>",
"<NSLayoutConstraint:0x8f77860 H:[UITextField:0x8f6ad70]-(NSSpace(8))-[UIButton:0x8f77500]>",
"<NSLayoutConstraint:0x8f778d0 H:[UIButton:0x8f77500]-(NSSpace(20))-| (Names: '|':UIView:0x8f77650 )>",
"<NSAutoresizingMaskLayoutConstraint:0x8fad160 h=--& v=--& H:[UIView:0x8f77650(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x8f77860 H:[UITextField:0x8f6ad70]-(NSSpace(8))-[UIButton:0x8f77500]>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
[ANONYMIZED][31422:70b] 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)
(
"<NSLayoutConstraint:0x8f77940 V:|-(NSSpace(20))-[UITextField:0x8f6ad70] (Names: '|':UIView:0x8f77650 )>",
"<NSLayoutConstraint:0x8f77980 V:[UITextField:0x8f6ad70]-(NSSpace(20))-| (Names: '|':UIView:0x8f77650 )>",
"<NSAutoresizingMaskLayoutConstraint:0x8fad1c0 h=--& v=--& V:[UIView:0x8f77650(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x8f77980 V:[UITextField:0x8f6ad70]-(NSSpace(20))-| (Names: '|':UIView:0x8f77650 )>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.