4
votes

I am designing a registration page view, programmatically, for my app where the user can enter in an image of themselves and some info.

In my LoginController I create a UINavigationController with a rootviewcontroller of my RegisterController which is then displayed.

func handleRegisterButtonClicked() {
    let registerController = RegisterController()
    let navController = UINavigationController(rootViewController: registerController)
    present(navController, animated: true, completion: nil)
}

Right now I have added a picture for them to click to upload their photo. I want this picture to always show up 30px underneath the navigation bar, but instead underlaps the navigation bar, showing up 30px from the top of the screen:

Portrait Orientated Landscape Orientated

class RegisterController: UIViewController {
...
func setupViews() {
    profilePic.topAnchor.constraint(equalTo: view.topAnchor, constant: 30).isActive = true
}

Is there a way to add a constraint to the profilePic so that it is anchored to the bottom of the navigation bar (in both portrait and landscape orientations)?

3

3 Answers

13
votes

Instead of view.topAnchor try topLayoutGuide.bottomAnchor. This should pin it to the bottom of the navigation bar (the view controller’s “top layout guide”).

func setupViews() {
    profilePic.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 30).isActive = true
}

iOS 11 or later

In iOS 11 topLayoutGuide and bottomLayoutGuide are deprecated in favor of safeAreaLayoutGuide (which is a UIView property, not UIViewController).

If your app will support iOS 11 you should do the following:

func setupViews() {
    if #available(iOS 11.0, *) {
        profilePic.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30).isActive = true
    } else {
        profilePic.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 30).isActive = true
    }
}

If/when your app only supports iOS 11 or later you can remove the conditional availability check and just go with the safeAreaLayoutGuide version.

1
votes

I fixed this by making the nav bar not translucent:

In RegisterController, try this:

- (void)viewDidLoad{
    [super viewDidLoad];
    self.navigationController.navigationBar.translucent = NO;
}
0
votes

In my case, I had to also disable the edgesForExtendedLayout property for a given view controller.

edgesForExtendedLayout = []