Trailing and leading restrictions in Swift programmatically (NSLayoutConstraints)

I am adding a view from xib to my ViewController. Then I put his restrictions so that they really correspond to him.

override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) ... ... view!.addSubview(gamePreview) gamePreview.translatesAutoresizingMaskIntoConstraints = false if #available(iOS 9.0, *) { // Pin the leading edge of myView to the margin leading edge gamePreview.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true //Pin the trailing edge of myView to the margin trailing edge gamePreview.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true } else { // Fallback on earlier versions view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .TrailingMargin, relatedBy: .Equal, toItem: view, attribute: .TrailingMargin, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .LeadingMargin, relatedBy: .Equal, toItem: view, attribute: .LeadingMargin, multiplier: 1, constant: 0)) } view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 131)) } 

What I'm trying to do: actually put my view, restricting it to the top, leading, moving into the ViewController and with a pre-set height. The view that I am adding to the main view has its own view with a transparent background, so there is no need for a field (the view is designed for the width of the device, therefore).

I placed two pairs of lines that should have been equal (in my attempts), with if, because the first 2 lines in if are really only available in iOS9>, while I try to do the same in the else statement for each device (starting with iOS 8).

This is what I get:

iOS9 + on the left, iOS8 + on the right. The transparent background was painted red to show what was happening (do not mind at different heights in the images, they are equal in height in the application, instead look at the added fields on the left and right)

I also tried AutoLayoutDSL-Swift , but it does not help, I am not an expert in this, but each attempt made it worse.

How can I write these restrictions using the classic NSLayoutConstraints methods and how could I write everything in the best possible way with a framework like AutoLayoutDSL or its fork? (or an alternative, although now I'm mostly concerned about official libraries)

+6
source share
2 answers

You need to use the leading and trailing attributes, not the leadingMargin and trailingMargin attributes:

 override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) ... ... view!.addSubview(gamePreview) gamePreview.translatesAutoresizingMaskIntoConstraints = false view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 131)) } 
+14
source

Guessed it thanks @ Paulw11 ... this solution

 view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: gamePreview, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 131)) 

I also managed to rewrite it as it should, using AutoLayoutDSL-Swift for all interested

 view => gamePreview.trailing == view.trailing => gamePreview.leading == view.leading => gamePreview.height == 131 => gamePreview.top == view.top + self.navigationController!.navigationBar.bounds.height + UIApplication.sharedApplication().statusBarFrame.size.height 

The last line is a little long because view.top refers to the top of the view and does not take into account the addition added by both the status and the navigationBar height. They could be replaced as constants, waiting if someone came up with a more elegant solution.

+2
source

All Articles