UIViewController: adjust contraints of xib - ios

In my project I defined a xib and a ViewController that will contain the xib.
class FeedDetailViewController: UIViewController, FeedDetailDelegate {
var feedDetail: FeedDetail!
override func viewDidLoad() {
super.viewDidLoad()
feedDetail = (NSBundle.mainBundle().loadNibNamed("FeedDetail", owner: self, options: nil)[0] as? UIView)! as! FeedDetail
feedDetail.delegate = self;
self.view.addSubview(feedDetail)
self.adjustContraints()
}
func adjustContraints() {
feedDetail.sizeThatFits(self.view.frame.size)
var constraint = NSLayoutConstraint(item: feedDetail,
attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: feedDetail,
attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: feedDetail,
attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
view.addConstraint(constraint)
constraint = NSLayoutConstraint(item: feedDetail,
attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
view.addConstraint(constraint)
self.view.layoutIfNeeded()
}
What I want is simply the xib at "fullscreen", but xib borders are not "sticked" to the main view of the controller.
Border legend:
red: self.view
yellow: feedDetail
others: element inside feedDetail (test only)

Try to call this method before adding constraints.
feedDetail.setTranslatesAutoresizingMaskIntoConstraints(false)

Related

Swift: Can't center UIView in Superview with NSLayoutConstraint

i'm trying to center a view in the parent view but its not centering as expected. Here is my code an a screenshot of the result.
emptyView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(emptyView)
let centerXConstraint = NSLayoutConstraint(item: emptyView, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
let centerYConstraint = NSLayoutConstraint(item: emptyView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0)
self.view.addConstraints([centerXConstraint])
self.view.addConstraints([centerYConstraint])
Here is the code,
import UIKit
class ViewController: UIViewController
{
#IBOutlet weak var emptyView: UIView!
override func viewDidLoad()
{
super.viewDidLoad()
self.emptyView.translatesAutoresizingMaskIntoConstraints = false
let centerXConstraint = NSLayoutConstraint(item: emptyView, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
let centerYConstraint = NSLayoutConstraint(item: emptyView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0)
let widthConstraint = NSLayoutConstraint(item: emptyView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: emptyView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
self.view.addConstraints([centerXConstraint, centerYConstraint, widthConstraint, heightConstraint])
self.view.layoutIfNeeded()
}
}
If you are using label or button or any other view that have intrinsic size, there is no need for height and width constraints
ViewController Interface :
Output :
Try this code
emptyView.translatesAutoresizingMaskIntoConstraints = false
let widthConstraint = NSLayoutConstraint(item: emptyView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: emptyView.frame.size.width)
let heightConstraint = NSLayoutConstraint(item: emptyView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: emptyView.frame.size.height)
var constraints = NSLayoutConstraint.constraints(
withVisualFormat: "V:[superview]-(<=1)-[label]",
options: NSLayoutFormatOptions.alignAllCenterX,
metrics: nil,
views: ["superview":view, "label": emptyView])
view.addConstraints(constraints)
// Center vertically
constraints = NSLayoutConstraint.constraints(
withVisualFormat: "H:[superview]-(<=1)-[label]",
options: NSLayoutFormatOptions.alignAllCenterY,
metrics: nil,
views: ["superview":view, "label": emptyView])
view.addConstraints(constraints)
view.addConstraints([ widthConstraint, heightConstraint])

Adding subview with constraints makes view black

I am trying to add a overlay over for all my viewcontrollers by adding this code to my "BaseViewController". However it result in all ViewControllers turning black and behaving oddly.
override public func viewDidLoad()
{
super.viewDidLoad()
overlayView = UIView()
overlayView.backgroundColor = UIColor.redColor() //For testing
view.addSubviewWithMatchingConstraints(overlayView)
...
}
And in UIView extension:
func addSubviewWithMatchingConstraints(subView: UIView)
{
translatesAutoresizingMaskIntoConstraints = false
addSubview(subView)
addConstraint(NSLayoutConstraint(item: subView, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint(item: subView, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint(item: subView, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1.0, constant: 0))
addConstraint(NSLayoutConstraint(item: subView, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1.0, constant: 0))
}
The issue was that I set translatesAutoresizingMaskIntoConstraints on the parent rather than the child.
childView.translatesAutoresizingMaskIntoConstraints = false
fixed it

Centering a UIView programmatically using Autolayout makes the view disappear from superview

I have the following code to simply center a red square using AutoLayout constraints programmatically in my ViewController's view:
class ViewController: UIViewController {
let square: UIView
required init?(coder aDecoder: NSCoder) {
let squareFrame = CGRectMake(0.0, 0.0, 500.0, 500.0)
self.square = UIView(frame: squareFrame)
super.init(coder: aDecoder)
}
override func viewDidLoad() {
self.view.addSubview(self.square)
self.square.backgroundColor = UIColor.redColor()
self.view.backgroundColor = UIColor.blueColor()
print(self.square)
setupConstraints()
print(self.square)
}
func setupConstraints() {
self.square.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal,
toItem: self.square, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant:0).active = true
NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal,
toItem: self.square, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant:0).active = true
}
}
The resulting screen however only shows the blue background, no sign of the red square... Even when using the view debugging feature in Xcode it can't be seen.
If I comment out setupConstraints(), it works as "expected" with the original frame that I gave the square during initialisation.
By the way, both print statements have the exact same output:
<UIView: 0x7ff1c8d3f3e0; frame = (0 0; 500 500); layer = <CALayer: 0x7ff1c8d04c00>>
How can this be when the square is nowhere to be seen?
Update:
The issue remains when I am adding width and height constraints as suggested by #HaydenHolligan in setupConstraints():
func setupConstraints() {
self.square.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal,
toItem: self.square, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant:0).active = true
NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal,
toItem: self.square, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant:0).active = true
// the following lines have no effect with respect to the issue mentioned aboove
let sizeFormat = "[square(100#100)]"
let size = NSLayoutConstraint.constraintsWithVisualFormat(sizeFormat, options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["square": self.square])
self.view.addConstraints(size)
}
Try to change your setupConstraints func to this :
func setupConstraints() {
self.square.translatesAutoresizingMaskIntoConstraints = false
let centerX = NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal,toItem: self.square, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant:0)
let centerY = NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal,toItem: self.square, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant:0)
let squareWidth = NSLayoutConstraint(item: self.square, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant:500)
let squareHeight = NSLayoutConstraint(item: self.square, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant:500)
self.view.addConstraints([centerX , centerY ,squareWidth , squareHeight])
}

Swift - Add NSLayoutConstraint to my Button

I want to have a button always in bottom and in left and right corner.
I want to do this with adding constraints to my button programatically.
My Code:
class LoginController: UIViewController {
#IBOutlet weak var LoginButton: UIButton!
override func loadView() {
super.loadView()
//Button Height Constraint
let constraintButtonPlayWidth = NSLayoutConstraint (item: self.LoginButton,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 1,
constant: 80)
self.view.addConstraint(constraintButtonPlayWidth)
//Button Right Constraint
let r = NSLayoutConstraint(item: self.LoginButton, attribute: .Right,
relatedBy: .Equal, toItem: self.view, attribute: .Right, multiplier: 1.0, constant: 0.0)
//Button Left Constraint
let l = NSLayoutConstraint(item: self.LoginButton, attribute: .Left,
relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 100.0)
//Button Bottom Constraint
let b = NSLayoutConstraint(item: self.LoginButton, attribute: .Bottom,
relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 100.0)
self.view.addConstraints([l,b,r])
When I run this code:
When i add Constraints in Designer:
and when i run the App it works
my Question: What is my mistake?
If you have a view in a storyboard with no constraints, the Interface Builder will generate some constraints automatically. These auto generated constraints will conflict with the code generated ones.
So, in my opinion you have four choices.
Generate Button in Code:
Create an Constraint in Interface Builder and remove them at build time by selecting constraint in Interface Builder and check "Remove at build time"
Remove auto generated Constraints in Code
Create Constraints in Interface Builder
Option 1 - Generate Button in Code
override func viewDidLoad()
{
super.viewDidLoad()
let button = UIButton()
button.setTitle("Login", forState: UIControlState.Normal)
button.backgroundColor = UIColor.redColor()
button.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button)
let heightConstraint = NSLayoutConstraint(
item: button,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 1.0,
constant: 80
)
button.addConstraint(heightConstraint)
let leftConstraint = NSLayoutConstraint(
item: button,
attribute: NSLayoutAttribute.Leading,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Leading,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(leftConstraint)
let rightConstraint = NSLayoutConstraint(
item: button,
attribute: NSLayoutAttribute.Trailing,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Trailing,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(rightConstraint)
let topConstraint = NSLayoutConstraint(
item: button,
attribute: NSLayoutAttribute.Bottom,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Bottom,
multiplier: 1,
constant: 0
)
self.view.addConstraint(topConstraint)
}
Option 2 - Constraints in Code (with Constraint in IB removed at build time)
Create at least one constraint (e.g. a height constraint on the login button) and set the Remove at build time checkbox. After that you will get storyboard errors, you can fix them by adding more constraints (but i think it is not really necessary to fix the storyboard errors)
override func viewDidLoad()
{
super.viewDidLoad()
self.LoginButton.translatesAutoresizingMaskIntoConstraints = false
let heightConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 1.0,
constant: 80
)
self.LoginButton.addConstraint(heightConstraint)
let leftConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Leading,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Leading,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(leftConstraint)
let rightConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Trailing,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Trailing,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(rightConstraint)
let topConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Bottom,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Bottom,
multiplier: 1,
constant: 0
)
self.view.addConstraint(topConstraint)
}
Option 3 - Remove auto generated Constraints in Code
override func viewDidLoad()
{
super.viewDidLoad()
var removeConstraints : [NSLayoutConstraint] = []
for constraint in self.view.constraints
{
if constraint.firstItem === self.LoginButton
{
removeConstraints.append(constraint)
}
}
self.view.removeConstraints(removeConstraints)
self.LoginButton.removeConstraints(self.LoginButton.constraints)
self.LoginButton.translatesAutoresizingMaskIntoConstraints = false
let heightConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 1.0,
constant: 80
)
self.LoginButton.addConstraint(heightConstraint)
let leftConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Leading,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Leading,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(leftConstraint)
let rightConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Trailing,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Trailing,
multiplier: 1.0,
constant: 0
)
self.view.addConstraint(rightConstraint)
let topConstraint = NSLayoutConstraint(
item: self.LoginButton,
attribute: NSLayoutAttribute.Bottom,
relatedBy: NSLayoutRelation.Equal,
toItem: self.view,
attribute: NSLayoutAttribute.Bottom,
multiplier: 1,
constant: 0
)
self.view.addConstraint(topConstraint)
}
Option 4 - Create in Interface Builder
Create Constraints in Interface Builder
If you want the button at the bottom, where you are setting the constraint, remove the 100 constant.
let b = NSLayoutConstraint(item: self.button, attribute: .Bottom,
relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
If you are targeting iOS 9 you can also add your constraints like this:
button.addConstraint(button.heightAnchor.constraintEqualToConstant(80))
self.view.addConstraint(self.view.leadingAnchor.constraintEqualToAnchor(button.leadingAnchor))
self.view.addConstraint(self.view.trailingAnchor.constraintEqualToAnchor(button.trailingAnchor))
self.view.addConstraint(self.view.bottomAnchor.constraintEqualToAnchor(button.bottomAnchor))

ScrollView Won't Scroll AHHH

For the life of me I can't figure out what I'm doing wrong. All I'm trying to do is put a bunch of text fields in a scroll view and have it intrinsically determine the contentSize using auto layout. Unlike the other tutorials I've watched and read out there, I'm trying to do this programmatically, not through Storyboards or Xibs.
I've called setTranslatesAutoresizingMaskIntoConstraints(false) on every view in the scroll view (including on the scroll view itself).
I've set the height and width of the scroll view to match it's superview and even positioned the scroll view in the center of it's superview (I read that sometimes you need to do that to get it working)
I've pinned the content view's edges to the top, leading, trailing, and bottom edges of it's superview (the scroll view)
Here's my code:
class ViewController: UIViewController {
var scrollView = UIScrollView()
var contentView = UIView()
var textField1 = CustomTextField()
var textField2 = CustomTextField()
var textField3 = CustomTextField()
var textField4 = CustomTextField()
var textField5 = CustomTextField()
var textField6 = CustomTextField()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
textField1.setTranslatesAutoresizingMaskIntoConstraints(false)
textField2.setTranslatesAutoresizingMaskIntoConstraints(false)
textField3.setTranslatesAutoresizingMaskIntoConstraints(false)
textField4.setTranslatesAutoresizingMaskIntoConstraints(false)
textField5.setTranslatesAutoresizingMaskIntoConstraints(false)
textField6.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(textField1)
contentView.addSubview(textField2)
contentView.addSubview(textField3)
contentView.addSubview(textField4)
contentView.addSubview(textField5)
contentView.addSubview(textField6)
contentView.backgroundColor = .redColor()
setupConstraints()
}
func setupConstraints() {
// Install height and width constraints on our scroll view
let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
let widthLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
self.view.addConstraints([heightLC,widthLC])
// Install centering constraints on our scroll view
let centerXLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0)
let centerYLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0)
self.view.addConstraints([centerXLC,centerYLC])
// Set the content view so it resizes with the same proportions on screen rotations //
let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])
// Setup the text field constraints
let textField1Top : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let textField1Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField1Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField1Top, textField1Leading, textField1Trailing])
let textField2Top : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField1, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField2Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField2Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField2Top, textField2Leading, textField2Trailing])
let textField3Top : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField2, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField3Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField3Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField3Top, textField3Leading, textField3Trailing])
let textField4Top : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField3, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField4Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField4Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField4Top, textField4Leading, textField4Trailing])
let textField5Top : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField4, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField5Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField5Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
contentView.addConstraints([textField5Top, textField5Leading, textField5Trailing])
let textField6Top : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField5, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
let textField6Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
let textField6Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
let textField6Bottom : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: contentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
contentView.addConstraints([textField6Top, textField6Leading, textField6Trailing, textField6Bottom])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And here's my CustomTextField class I use for the text fields:
class CustomTextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .whiteColor()
// set text field height to 55pts
let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 55)
addConstraint(heightLC)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here's what the app currently looks like
(notice the 6th text field isn't being displayed and I can't scroll down to it):
Any help will greatly be appreciated :)
The problem is these lines:
let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])
What you want is not for the content view to be sized like the scroll view at all. That is exactly what is keeping the scroll view from scrolling. You want the content view's four edges to be pinned to the four edges of the scroll view.
That way, the contents of the content view will push outwards on the content view, sizing it. It will thus try to become bigger than the scroll view. But it can't, because you're also going to pin the sides of the scroll view to its superview. Thus, the content view's size will become the bounds size of the scroll view - its contentSize. When the contentSize of the scroll view is thus bigger than the scroll view, it will be scrollable.

Resources