Reputation: 1013
One for the auto-layout gurus out there: I don't understand why the following auto-layout setup prevents resizing of the window.
I have three views organized this way:
-----------------
| | |
| F | S |
| | |
-----------------
| B |
-------------
S has a fixed with, B has a fixed height, and F should always have S's height and B's width. This is what I set up in terms of constraints:
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[F(>=100)][S(==100)]|"
options:0
metrics:nil
views:@{ @"F": _f, @"S": _s }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[F(>=100)][B(==100)]|"
options:0
metrics:nil
views:@{ @"F": _f, @"B": _b }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[B(==F)]"
options:0
metrics:nil
views:@{ @"B": _b, @"F": _f }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[S(==F)]"
options:0
metrics:nil
views:@{ @"S": _s, @"F": _f }]];
The way I see things, this should allow me to resize the window freely, with F resizing to fill the space. But the constraints lock the window resizing completely.
Any idea what I'm doing wrong?
Thanks
Upvotes: 4
Views: 1504
Reputation: 5349
I have seen this same basic issue crop up several times because one of the view's translatesAutoresizingMaskIntoConstraints
property is YES.
This used to be controlled by a checkbox in Xcode's UI editor, but in Xcode 6.1.1 the checkbox is gone. However, for views created in code (e.g. WKWebView, which doesn't support instantiation from a .xib file), or for views created with earlier versions of Xcode, this property might be set to YES.
If so, that can cause auto-layout to behave in unexpected ways, often including your symptom that the window cannot be resized. You have manually configured the view to be resized with the window, but the automatic translation of autoresizing mask to constraints might add additional constraints, that cannot be simultaneously fulfilled if the window grows.
To illustrate, consider the method below. This extends NSView to add a method that resizes another view to the receiver's size, adds it as a subview of the receiver, and sets up auto-layout constraints so that the subview grows and shrinks with its superview (the receiver).
However, we noticed a bug here, where it usually worked correctly, but sometimes the window containing all the views would become un-resizable. The reason turned out to be that subview.translatesAutoresizingMaskIntoConstraints
was YES in some cases — and this caused unwanted additional layout constraints that prevented the window from resizing. Adding the second-to-last line fixed that bug.
That might be what is happening in your case (depending on how your views are being created).
@implementation NSView (Nakahara)
- (void)nakahara_embedSubview:(NSView *)subview;
{
subview.frame = self.bounds;
[self addSubview:subview];
NSArray *newConstraints =
@[
[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0],
[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0],
[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0],
[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0],
];
subview.translatesAutoresizingMaskIntoConstraints = NO;
// IMPORTANT! It took a while to figure out why this was sometimes working and sometimes not. It was because subview.translatesAutoresizingMaskIntoConstraints is sometimes YES and sometimes NO, and if it is YES, autolayout will break in undefined ways (e.g., windows suddenly become unresizable).
[self addConstraints:newConstraints];
}
@end
Upvotes: 2
Reputation: 502
When you create a new constraint, the default priority is 1000 (NSLayoutPriorityRequired
). This means that the auto layout engine will potentially affect the window size in order to satisfy your constraints.
If you set the priorities of your constraint to something less than 500 (NSLayoutPriorityWindowSizeStayPut
), you should get the behaviour you want.
Upvotes: 1