With Auto Layout, there are (at least) three possible ways to constrain a view so that it occupies the entire window’s content view, resizing when appropriate.
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
NSDictionary *views = NSDictionaryOfVariableBindings(customView);
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|"
options:0
metrics:nil
views:views]];
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|"
options:0
metrics:nil
views:views]];
(this should be equivalent to the visual format above)
+ (void)addEdgeConstraint:(NSLayoutAttribute)edge superview:(NSView *)superview subview:(NSView *)subview {
[superview addConstraint:[NSLayoutConstraint constraintWithItem:subview
attribute:edge
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:edge
multiplier:1
constant:0]];
}
and
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeLeft superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeRight superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeTop superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeBottom superview:contentView subview:customView];
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
The third approach is the one listed in the question and it may not work if there are further constraints. For example, without:
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
the original autoresize mask is applied as well, which leads to the behaviour described in the question: the window isn’t resized.
As mentioned by Regexident, you can use:
[_window visualizeConstraints:[contentView constraints]];
to debug Auto Layout. It’s worth checking the console output as well.
@Bavarious's answer is good, I will just add a few more things.
It's really important to learn to use the built in debugging support! As with much development, it is not realistic to hope that you will always get everything right on the first shot. This was a major concern with auto layout, so we put a lot of effort into debugging. Steps, briefly:
Usually the kind of question you'd post (my stuff doesn't work!) will not be enough for people to tell what's wrong, which is one of the reason's it's important to use the debugging stuff. See the WWDC 2011 session video (free for all) and docs for more on this.
Buuuuut I can actually tell what went wrong this time. :-) Before you turned off translatesAutoresizingMaskIntoConstraints, you were more constrained than you wanted to be - the width and height of your view were fixed as well, which is why the window couldn't resize. AFTER you turned it off though, you had ambiguous layout, because you hadn't fastened your view onto anything! You had said how big it should be (same as the superview), but not where it was supposed to be.
Ken
Cocoa Frameworks, primary auto layout author
You can create constraints with Layout Anchors with very easy to read format:
Swift2 code
func fit(childView: UIView, parentView: UIView) {
childView.translatesAutoresizingMaskIntoConstraints = false
childView.topAnchor.constraintEqualToAnchor(parentView.topAnchor).active = true
childView.leadingAnchor.constraintEqualToAnchor(parentView.leadingAnchor).active = true
childView.trailingAnchor.constraintEqualToAnchor(parentView.trailingAnchor).active = true
childView.bottomAnchor.constraintEqualToAnchor(parentView.bottomAnchor).active = true
}
Use:
parrentView.addSubview(childView)
fit(childView, parentView: parrentView)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With