Bohdan Orlov
iOS Developer @Badoo
To memory of -setFrame: and CGRectDivide()
Red circle:
Yellow triangle:
There are multiple ways to achieve same result with different constraints
We can resolve this by adding additional constraints with priority less than required.
For example we can say:
View.width = width @ 750
static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000;
static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750;
static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250;
// the priority level with which the view wants to conform to the target size.
static const UILayoutPriority UILayoutPriorityFittingSizeLevel NS_AVAILABLE_IOS(6_0) = 50;
For iOS 9+ we should use UIStackView
Constraints can be setup only on view attributes, but not other constraints.
We have to use dummy spacing views, with equal width constraint and 0 leading/trailing to neighbours
For iOS 9+ we should use UIStackView
Constraints can be setup only on view attributes, but not other constraints.
We have to use dummy container view
Override for custom/frame based views, invalidate it when appropriate
You can use UIViewNoIntrinsicMetric for width or height
Intrinsic content size of a view refers to its alignment rect, not to its frame.
The intrinsic content size of multiline UILabel depends on the width of the lines, which is yet to be determined when solving the constraints.
- (void)layoutSubviews {
[super layoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[super layoutSubviews];
}
H:[label(<=100@250)]
V:[label(<=30@250)]
H:[label(>=100@750)]
V:[label(>=30@750)]
Size Classes depends on:
<- iPhone 6 Plus is exception
iPhones' Size Classes
Adding or removing views
Adding or removing constraints
Changing the font in labels, fields, text views, and buttons
Counterexamples
Examples
Dos:
Don'ts:
SHIFT + OPT + LMB
SHIFT + CTRL + LMB
^ + OPT
Drag with CTRL to view
<+ SHIFT
to add multiple
^ LMB + LMB
@IBInspectable / @IBDesignable
Simulated metrics
Strong Outlets (again)
Сanvas configuration
Multiple nav bar items
Сanvas configuration
Multiple nav bar items
NSLayoutAnchor/UILayoutGuide available since iOS 9
// Ensures that all pending layout operations have been completed
[containerView layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
// Make all constraint changes here
// Forces the layout of the subtree animation block and captures all of the frame changes
[containerView layoutIfNeeded];
}];
override func layoutSubviews() {
mySubview.frame = CGRectMake(...)
}
- (void)updateConstraints {
[self removeConstraints:self.imageViewConstraints];
self.imageViewConstraints = [self createConstraints];
[self addConstraints:self.imageViewConstraints];
[super updateConstraints];
}
- (UIView *)viewForBaselineLayout
{
// create the view if not exists, start with rect zero
if (!self.baselineView) {
...
}
int integerBaseline = ...
// update the frame of the view
self.baselineView.frame = CGRectMake(0, 0, self.bounds.size.width, (float)integerBaseline);
return self.baselineView;
}
- constraintsAffectingLayoutForAxis:
- hasAmbiguousLayout
- exerciseAmbiguityInLayout
*<UIWindow:0x7fe781d25a80> - AMBIGUOUS LAYOUT
| *<UIView:0x7fe781d29db0>
| | *<UIButton:0x7fe781d2a170>
| | | <UIButtonLabel:0x7fe781c107d0>
| | *<UISlider:0x7fe781d2b9b0>
| | | <UIView:0x7fe781d37fe0>
| | | | <UIImageView:0x7fe781d3a780>
| | | <UIImageView:0x7fe781d3ac50>
| | | <UIImageView:0x7fe781d3e590>
| | | | <UIImageView:0x7fe781d39a00>
| | *<_UILayoutGuide:0x7fe781d2c4b0> - AMBIGUOUS LAYOUT
| | *<_UILayoutGuide:0x7fe781d2cda0> - AMBIGUOUS LAYOUT
expr ((UIView *)0x7731880).backgroundColor = [UIColor purpleColor]
po [[UIWindow keyWindow] _autolayoutTrace];