Creating Auto Layout constraints to topLayoutGuide and bottomLayoutGuide in code

28,029

Solution 1

For a UIButton that you want to place 20 points below the UIViewController.topLayoutGuide you create the NSLayoutConstraint like so:

[NSLayoutConstraint constraintWithItem:self.button
                             attribute:NSLayoutAttributeTop
                             relatedBy:NSLayoutRelationEqual
                                toItem:self.topLayoutGuide
                             attribute:NSLayoutAttributeBottom
                            multiplier:1.0
                              constant:20.0];

With iOS 9 you can also create the NSLayoutConstraint this way:

[self.button.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor
                                      constant:20.0];

Solution 2

To supplement @JamieMcDaniel's answer, the Swift + iOS9 version would be:

self.button.topAnchor
    .constraintEqualToAnchor( self.topLayoutGuide.bottomAnchor ).active = true

Don't forget the .active = true part as otherwise the constraint doesn't kick in automatically.

Solution 3

Just an addition to @Jamie McDaniel, in case it's not immediately obvious, you need to add the constraint that he suggests to create:

NSLayoutConstraint *buttonTopConstraint = [NSLayoutConstraint constraintWithItem:self.button
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.topLayoutGuide
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:20.0];
[self.view addConstraint:buttonTopConstraint];

Solution 4

This is a gist I've created, you are supposed to embed all your subviews into a tank view(container view) added into a xib, it removes tank view-superview xib constraints and adds an upper constraints to topLayoutGuide giving an iOS6 look. It could be interesting for what you want to achieve.

//This should be added before the layout of the view
- (void) adaptToTopLayoutGuide {
    //Check if we can get the top layoutguide
    if (![self respondsToSelector:@selector(topLayoutGuide)]) {
        return;
    }
    //tankView is a contaner view
    NSArray * array = [self.tankView referencingConstraintsInSuperviews]; //<--For this method get the Autolayout Demistified Book Sample made by Erica Sadun
    [self.view removeConstraints:array];
    NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topLayoutGuide]-0-[tankView]|" options:0 metrics:nil views:@{@"tankView": self.tankView, @"topLayoutGuide":self.topLayoutGuide}];
    [self.view addConstraints:constraintsVertical];
    NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tankView]|" options:0 metrics:nil views:@{@"tankView": self.tankView}];
    [self.view addConstraints:constraintsHorizontal];

}
Share:
28,029
smileyborg
Author by

smileyborg

Updated on July 08, 2022

Comments

  • smileyborg
    smileyborg almost 2 years

    Apple's documentation on creating Auto Layout constraints between a view and one of the layout guides only shows an example using VFL.

    Is there any way to create these constraints programmatically without VFL (using NSLayoutConstraint's other API or similar)?

    (Note: I'm specifically asking about doing this in code, not in Interface Builder. And I don't want the calculated length of the guide set as a static constant on a constraint, I want a constraint where changes to the layout guide length would automatically cause the constrained view to adjust position.)

  • smileyborg
    smileyborg over 10 years
    Sorry, but this doesn't address my specific question.
  • Andrea
    Andrea over 10 years
    VLF is the way to go with autolayout, I can't find any specific reason for not using it, I've just suggested a piece of code that could help you to point into the right direction.. If you want to think about it.
  • smileyborg
    smileyborg over 10 years
    VFL has it's own set of pros and cons. I am personally not a big fan of it, that's why I wrote this Auto Layout category on UIView which solves even more use cases than VFL can. I've even written some pros/cons of all the Auto Layout approaches (including VFL) on the README of that project.
  • Andrea
    Andrea over 10 years
    Really interesting... I've read the readme and I agree with your points, the thing that I'm missing is the Use case, I mean why use normal layout for general purpose layouting, instead of VLF?, performance?or something else?
  • smileyborg
    smileyborg over 10 years
    What do you mean by "normal layout"?
  • Andrea
    Andrea over 10 years
    I mean create each single constraint programmatically without using VLF, until now I've never found it limiting in general use. I'm just curious why would someone use single constraint instead of VLF, I understand that maybe there are exceptions about sort of particular layouting. Is there a performace reason?
  • smileyborg
    smileyborg over 10 years
    Take a look at the what the auto layout code looks like in the example project on GitHub. In my opinion, it's nicer to read & write than VFL (less crazy syntax, more Obj-C like). It's not about performance at all. But it is about compiler checking, easier debugging (knowing exactly what each line is doing), and easier learning curve among other things.
  • smileyborg
    smileyborg over 10 years
  • smileyborg
    smileyborg over 10 years
    You're (half?) right. Your code does work, but NSLayoutAttributeBaseline is not required to get it to work. If you're pinning to the topLayoutGuide, NSLayoutAttributeBottom works the same (and NSLayoutAttributeTop should be used when pinning to the bottomLayoutGuide of course). Anyways...I thought I tried this approach before and it didn't work...guess I screwed something up.
  • Ferran Maylinch
    Ferran Maylinch almost 9 years
    Andrea, it's a shame you got negative points for a correct answer that is even really useful! Both VFL and constraintWithItem methods are right, it's just a matter of taste. I prefer VFL whenever possible, I just miss some features like centering. To cut some code I created a really simple Autolayout helper, just in case you find it useful.
  • Jamie McDaniel
    Jamie McDaniel over 8 years
    Thanks @smileyborg. I also updated my answer to include the new iOS 9 API.
  • Michael Kessler
    Michael Kessler about 8 years
    I'd suggest to change the vertical constraint(s) from @"V:|[topLayoutGuide]-0-[tankView]|" to @"V:[topLayoutGuide][tankView]|" (removed the relation between the top of the superview and the top layout guide and the -0- between the top layout guide and tankView)...