Create constraints between two subviews programmatically - ios

I have a contentview inside a scrollview along with some other views, and scrollview height will change based on contentview height, and the height of the contentview is decided by the height of its subviews.
I am adding two subviews to contentview programmatically.
childView1 = CustomView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 200))
childView2 = CustomView(frame: CGRect(x: 0, y: 210, width: self.view.frame.width, height: 200))
contentView.addSubview(childView1)
contentView.addSubview(childView2)
// childView1 top should be equal to contentView top
let topConstraint = NSLayoutConstraint(item: childView1, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 0)
// childView2 bottom should be equal to contentView bottom
let bottomConstraint = NSLayoutConstraint(item: childView2, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 0)
// childView1 leading should be equal to contentView leading
let leadingConstraint1 = NSLayoutConstraint(item: childView1, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 0)
// childView1 trailing should be equal to contentView trailing
let trailingConstraint1 = NSLayoutConstraint(item: contentView1, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0)
// childView2 leading should be equal to contentView leading
let leadingConstraint2 = NSLayoutConstraint(item: childView2, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 0)
// childView2 trailing should be equal to contentView trailing
let trailingConstraint2 = NSLayoutConstraint(item: childView2, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0)
// Vertical Space between two child views is 10
let constraintTwoSubViews = NSLayoutConstraint(item: childView1, attribute: .bottom, relatedBy: .equal, toItem: childView2, attribute: .top, multiplier: 1, constant: 10)
contentView.addConstraints([topConstraint , bottomConstraint , leadingConstraint1,trailingConstraint1 , leadingConstraint2 , trailingConstraint2 , constraintTwoSubViews])
The problem is that the contentView height is not growing as per the subviews.
Because of that my scroll views is not growing.
When I am adding second child view, I do not want to specify y = 210
, I want its position to be calculated by space constraint between
two child views, Is it possible?
How can I make content view height grow as per its subviews?

What I do when I need a scrollable view:
I add a scrollView to the hierarchy and use autolayout to properly layout it, e.g., if it is supposed to cover the whole view of the viewController:
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
scrollView.topAnchor.constraint(equalTo: self.view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
])
Then you need to add a contentView to the scrollView and provide a proper layout constraints for it, so if you want vertically scrollable scrollView in the example I started above, you need following autolayout constraints:
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// horizontal anchors of contentView are constrained to scrollView superview
// to prevent it from scrolling horizontally
contentView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
contentView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
// but vertical anchors of contentView are constrained to
// scrollView to allow scrolling
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
Notice here that I constrained the leftAnchor and rightAnchor of the contentView to the self.view rather than to scrollView to make it of fixed width. However, top and bottom anchors are constrained to the scrollView, so they are expanded and scrollable when contentView needs more space.
Now you add to the contentView all the content that you want, and you lay it out using autolayout as if the contentView was a view with infinite height - scrollView will take care of presenting it whole by scrolling. In your case I think you can use UIStackView to lay out those two views. However, CustomView's frames will be calculated using autolayout, so I don't think you can rely on setting the frames directly - therefore I use constraints to set their heights too (widths will be stretched by the stackView):
let stack = UIStackView()
stack.spacing = 10
stack.distribution = .fill
stack.alignment = .fill
stack.axis = .vertical
contentView.addSubview(stack)
stack.addArrangedSubview(childView1)
stack.addArrangedSubview(childView2)
childView1.translatesAutoresizingMasks = false
childView2.translatesAutoresizingMasks = false
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: stack.topAnchor),
contentView.leadingAnchor.constraint(equalTo: stack.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: stack.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: stack.bottomAnchor),
// setting their heights using constraints
childView1.heightAnchor.constraint(equalToConstant: 200),
childView2.heightAnchor.constraint(equalToConstant: 200),
])

Related

Sizing label with Autolayout

Description of the issue
I have a label to the left side of a plot view in an iOS App.
I have succeeded in rotatif the label 90 degrees, as pictured below, using the code copied in a following section :
However, as soon as I change the text to "Speed (Km/h):, the label becomes wider, as shown below :
Layout
There are no relevant contraints were set in interface builder. The only contraints set here are :
- vertical centering of the label
- plot view's right, top, and bottom edges stick to view's right, top, and bottom edges
The rest is set in code
Code
func setup(speedArray: [Float32]) {
//Convert speed to Km/h from m/s
let speedArrayKMH = speedArray.map({$0*3.6})
//Draw Chart
//This only styles the chart (colors, user interaction, etc...
//no code in this fuction that affects layout)
setupSpeedChart(speedArray: speedArrayKMH)
//
// Customise speed label
//
//Label text
chartTitleLabel.textAlignment = .center
//Text color
self.chartTitleLabel.textColor = BoxTextColor
//Rotate
chartTitleLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
//Constrain
let C1 = NSLayoutConstraint(item: chartTitleLabel, attribute: .leadingMargin, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 0)
let C2 = NSLayoutConstraint(item: chartTitleLabel, attribute: .trailingMargin, relatedBy: .equal, toItem: speedLineChart, attribute: .leading, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([C1, C2])
}
What I've tried
I've tried a number of construit and size combinations, including :
fixing the label's frame property (height and width)
adding a constraint for the label's width and height
nothing seems to work
Adding the following constraint for label width for example produces this :
let C3 = NSLayoutConstraint(item: chartTitleLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 45)
there are few key thing missing
first you forgot to use translateAutoReaizingMaskIntoConstraints
go to storyboard select your label go to inspector under label there is autoshrink set it to minimum font size set the size to 11
then do the following in view didload
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
myLabel.text = "speed in km"
myLabel.textAlignment = .center
myLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
myLabel.translatesAutoresizingMaskIntoConstraints = false
let c1 = NSLayoutConstraint(item: myLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)
let c2 = NSLayoutConstraint(item: myLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 60)
let c3 = NSLayoutConstraint(item: myLabel, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: -60)
let c4 = NSLayoutConstraint(item: myLabel, attribute: .centerY, relatedBy: .equal, toItem: myImageView, attribute: .centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([c1, c2, c3, c4])
}
I have tried to update the text to new text with more character count than previous and I worked just fine
The issue lies in this part of the description of transform in Apple's docs: https://developer.apple.com/documentation/uikit/uiview/1622459-transform
In iOS 8.0 and later, the transform property does not affect Auto Layout. Auto layout calculates a view’s alignment rectangle based on its untransformed frame.
So, when you change the text of the label, your constraints are related to the untransformed frame.
The fix is to embed the label in a "container" UIView and constrain the container's width to the height of the label, and the height to the width of the label.
Set up your xib like this (I use contrasting background colors to make it easy to see frames):
Note that I've given the container view width and height constraints of 80. Edit each of those constraints and set them as "Placeholders":
We'll be setting new constraints in code, so these will be removed at build time, but will satisfy IB's layout checking.
In awakeFromNib() in your custom class, add the new width and height constraints and apply the rotation transform:
override func awakeFromNib() {
super.awakeFromNib()
// set HUGGING priority on title label to REQUIRED for both axis
chartTitleLabel.setContentHuggingPriority(.required, for: .horizontal)
chartTitleLabel.setContentHuggingPriority(.required, for: .vertical)
NSLayoutConstraint.activate([
// constrain title container view WIDTH equal to title label HEIGHT
// set the constant to add padding on left and right of rotated title label
// here it is set to 12, which gives 6-pts padding on each side
chartTitleContainerView.widthAnchor.constraint(equalTo: chartTitleLabel.heightAnchor, constant: 12.0),
// constrain title container view HEIGHT equal to title label WIDTH
chartTitleContainerView.heightAnchor.constraint(equalTo: chartTitleLabel.widthAnchor, constant: 0.0),
])
// rotate the title label
chartTitleLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
// un-comment after development
// chartTitleLabel.backgroundColor = .clear
// chartTitleContainerView.backgroundColor = .clear
}
Now, in your setup() func (where, I'm assuming, you add the "plot view" as a subview), add the constraints for the plot view:
func setup(speedArray: [Float32]) {
//Convert speed to Km/h from m/s
let speedArrayKMH = speedArray.map({$0*3.6})
// assuming setupSpeedChart() creates speedLineChart view and adds it to self
//Draw Chart
//This only styles the chart (colors, user interaction, etc...
//no code in this fuction that affects layout)
setupSpeedChart(speedArray: speedArrayKMH)
NSLayoutConstraint.activate([
// constrain chart view LEADING to title container view TRAILING
speedLineChart.leadingAnchor.constraint(equalTo: chartTitleContainerView.trailingAnchor, constant: 0.0),
// constrain chart view top, bottom and trailing to self
speedLineChart.topAnchor.constraint(equalTo: topAnchor, constant: 0.0),
speedLineChart.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0.0),
speedLineChart.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0),
])
}
This is the result:
and with the "dev" colors turned off:
You can now change the text of the title label and it will remain centered vertically and horizontally, without changing the horizontal size / spacing.

Swift insert big height label into view

I'm new to the Swift and trying to add label programmatically to UIView which is embedded into scroll view.
Actually, i want to have something with header (picture and title for half of the screen) and content below (text with unknown length and images).
I'm added a view container and depending on content i want to add label or image view.
Most of the time it will be like that:
text
image
text
image
and so on.
Add label code (Swift 4):
let label = UILabel()
label.numberOfLines = 0
label.text = blogItem.text
containerView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: containerView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: containerView, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: containerView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: containerView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0).isActive = true
The problem is that text is truncated, when comes to the end of the screen and no scrolling at all.
How can i add bottom constraint correctly (i believe that's all happens because of it?) to make expected behaviour?
Make sure you created a proper hierarchy for working UIScrollView:
Add a scrollView to the hierarchy and use autolayout to properly layout it, e.g., if it is supposed to cover the whole view of the viewController:
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
scrollView.topAnchor.constraint(equalTo: self.view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
])
Then you need to add a contentView to the scrollView and provide a proper layout constraints for it, so if you want vertically scrollable scrollView in the example I started above, you need following autolayout constraints:
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// horizontal anchors of contentView are constrained to scrollView superview
// to prevent it from scrolling horizontally
contentView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
contentView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
// but vertical anchors of contentView are constrained to
// scrollView to allow scrolling
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
Notice here that I constrained the leftAnchor and rightAnchor of the contentView to the self.view rather than to scrollView to make it of fixed width. However, top and bottom anchors are constrained to the scrollView, so they are expanded and scrollable when contentView needs more space.
Now you add to the contentView all the content that you want, and you lay it out using autolayout as if the contentView was a view with infinite height - scrollView will take care of presenting it whole by scrolling. So in my example if the only content would be one huge UILabel with many lines (label is a subview of contentView):
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.leftAnchor.constraint(equalTo: contentView.leftAnchor),
label.rightAnchor.constraint(equalTo: contentView.rightAnchor),
label.topAnchor.constraint(equalTo: contentView.topAnchor),
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
Try to go over your code and check your constraints. It might be that you miss constraints in both cases, and the fact that it works in first case is just a coincidence.

Programmatic Autolayout changes behaviour of a UIView

I have a controller where I add a subview programmatically. With the configuration of the subview I add autolayout constraints programmatically. Everthing is working except that the view doesn't react on touches if I add the constraints and even the set backgroundcolor is not displayed.
The buttonView should be displayed in the lower right corner of my parent view.
Any ideas what could be wrong?
Here is how I add my constraints:
private func configureAutolayoutConstraints(buttonView: UIView, parentView: UIView){
buttonView.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = NSLayoutConstraint(item: buttonView, attribute:
.Bottom, relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: -130)
parentView.addConstraint(bottomConstraint)
let trailingConstraint = NSLayoutConstraint(item: buttonView, attribute:
.Trailing, relatedBy: .Equal, toItem: parentView, attribute: .Trailing, multiplier: 1.0, constant: -90)
parentView.addConstraint(trailingConstraint)
}
Autolayout engine needs at least 4 constraints to determine the frame of view. You have applied bottom and trailing constraints only. You need either width+height OR leading+top constraint to make it work.

Badge view how to create with a full auto layout approach

It's been a while since I'm trying to create a custom view that has at the top right corner a simple badge.
The custom view is composed by 3 part.
In red there is the custom view itself, that contains:
in blue the container view
in green the badge view a simple UILabel
Container view and the badge view are sibling.
At the moment the container view contains a UIImageView
That view must fit those requirements:
Full auto layout approach
Made programmatically
The custom view must be aligned only considering the blue frame(the container view)
Why that? imagine that you need to position that view by aligning the top edge to the top edge of another view or button, wouldn't be nice if the only the content showed int he container is taken into account?
Here you can see how I set the constraints. The label is placed at the top right corner of the container view.
func setUpConstraint() {
var horContraints = [NSLayoutConstraint]()
horContraints.append(NSLayoutConstraint(item: containerView, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1, constant: 0))
horContraints.append(NSLayoutConstraint(item: containerView, attribute: .Trailing, relatedBy: .Equal, toItem: badge, attribute: .CenterX, multiplier: 1, constant: 0))
horContraints.append(NSLayoutConstraint(item: badge, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: 0))
var verContraints = [NSLayoutConstraint]()
verContraints.append(NSLayoutConstraint(item: containerView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: 0))
verContraints.append(NSLayoutConstraint(item: containerView, attribute: .Top, relatedBy: .Equal, toItem: badge, attribute: .CenterY, multiplier: 1, constant: 0))
verContraints.append(NSLayoutConstraint(item: badge, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0))
addConstraints(verContraints + horContraints)
containerView.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Height, relatedBy: .Equal, toItem: containerView, attribute: .Width, multiplier: 1, constant: 0))
}
The container view has also an aspect ratio constraint to keep a square size.
As you can see from the picture everything seems to be fine, except for the fact that when I try to constraint the custom view to the center of its superview, it seems misaligned, because I want the view to be centered respect to the container view (the one with the image). The badge is a kind of decoration such as a shadow and I don't want it to be consider.
To align it correctly I'm trying to override the alignment rect by adding an insets that would "cut" half the label size.
override func alignmentRectInsets() -> UIEdgeInsets {
let badgeSize = badge.bounds.size
return UIEdgeInsets(top: badgeSize.height / 2, left: 0, bottom: 0, right: badgeSize.width / 2)
}
I tried also different configurations but I never was able to fit in the wanted position
If I try to use the other 2 methods alignmentRectForFrame and frameForAlignmentRect (deleting alignmentRectInsets) they are never be called.
Here is what I'd like to obtain:
I've created a little sample code
If the problem is that you want the other view (the "content view", showing the image) to be centered in the ultimate superview, then simply make centering constraints (center x to center x, center y to center y) between the superview and the content view. No law says that a constraint has to be between a view and its direct superview; you can make constraints between any pair of views (that is one of the wonderful things about constraints).
I made a quick mock-up that looks a lot like your "here's what I'd like to obtain" image:
As you can see, Moe (the middle Pep Boy, in the middle of the image) is exactly centered in the superview (shown by the green lines).
For simplicity, the entire interface is created in code, so that I can show you the whole thing. Here it is:
// create the custom view
let customView = UIView()
customView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(customView)
customView.backgroundColor = UIColor.redColor()
NSLayoutConstraint.activateConstraints([
customView.widthAnchor.constraintEqualToConstant(100),
customView.heightAnchor.constraintEqualToConstant(100),
])
// add the content view (image) to the custom view
let contentView = UIImageView(image: UIImage(named:"pep.jpg")!)
contentView.translatesAutoresizingMaskIntoConstraints = false
customView.addSubview(contentView)
NSLayoutConstraint.activateConstraints([
contentView.leadingAnchor.constraintEqualToAnchor(customView.leadingAnchor),
contentView.bottomAnchor.constraintEqualToAnchor(customView.bottomAnchor),
contentView.heightAnchor.constraintEqualToAnchor(customView.heightAnchor, constant: -10),
contentView.widthAnchor.constraintEqualToAnchor(customView.widthAnchor, constant: -10)
])
// add the badge (label) to the custom view
let badge = UILabel()
badge.translatesAutoresizingMaskIntoConstraints = false
customView.addSubview(badge)
badge.backgroundColor = UIColor.greenColor().colorWithAlphaComponent(0.5)
badge.font = UIFont(name: "GillSans", size: 14)
badge.textAlignment = .Center
badge.text = "567"
NSLayoutConstraint.activateConstraints([
badge.centerXAnchor.constraintEqualToAnchor(contentView.trailingAnchor),
badge.centerYAnchor.constraintEqualToAnchor(contentView.topAnchor),
])
// position the whole thing with respect to the content view
NSLayoutConstraint.activateConstraints([
contentView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor),
contentView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor),
])
But this is not a complete answer to your question. You should now be asking: Yes, but what went wrong when I tried to use the alignmentRectInsets? The answer is: you forgot that the alignmentRectInsets affect alignment with internal views as well as external views. In other words, you certainly can use that approach instead, but then you must adjust the position of the content view accordingly.
So, here's a rewrite in which I use the alignmentRectInsets. First, I'll define a custom view subclass for our custom view:
class AlignedView : UIView {
override func alignmentRectInsets() -> UIEdgeInsets {
return UIEdgeInsetsMake(10, 0, 0, 10)
}
}
Now here's the rewrite. I've put a star (*) next to all the lines that have changed from the previous example:
// create the custom view
let customView = AlignedView() // *
customView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(customView)
customView.backgroundColor = UIColor.redColor()
NSLayoutConstraint.activateConstraints([
customView.widthAnchor.constraintEqualToConstant(100),
customView.heightAnchor.constraintEqualToConstant(100),
])
// add the content view (image) to the custom view
let contentView = UIImageView(image: UIImage(named:"pep.jpg")!)
contentView.translatesAutoresizingMaskIntoConstraints = false
customView.addSubview(contentView)
NSLayoutConstraint.activateConstraints([
contentView.leadingAnchor.constraintEqualToAnchor(customView.leadingAnchor),
contentView.bottomAnchor.constraintEqualToAnchor(customView.bottomAnchor),
contentView.heightAnchor.constraintEqualToAnchor(customView.heightAnchor), // *
contentView.widthAnchor.constraintEqualToAnchor(customView.widthAnchor) // *
])
// add the badge (label) to the custom view
let badge = UILabel()
badge.translatesAutoresizingMaskIntoConstraints = false
customView.addSubview(badge)
badge.backgroundColor = UIColor.greenColor().colorWithAlphaComponent(0.5)
badge.font = UIFont(name: "GillSans", size: 14)
badge.textAlignment = .Center
badge.text = "567"
NSLayoutConstraint.activateConstraints([
badge.centerXAnchor.constraintEqualToAnchor(contentView.trailingAnchor),
badge.centerYAnchor.constraintEqualToAnchor(contentView.topAnchor),
])
// position the whole thing with respect to the custom view
NSLayoutConstraint.activateConstraints([
customView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor), // *
customView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor), // *
])
That gives exactly the same visual result as before.

Align UILabel along bottom of its parent view using Autolayout

I am attempting to display a UILabel centered at the bottom of its parent view, with leading and trailing set to stretch to the parent view's bounds. Unfortunately, the label isn't appearing on screen at all. I have verified the parent view is correctly filling the entire screen as desired.
//set up parent view
let vibrancyEffect = UIVibrancyEffect(forBlurEffect: blurEffect)
let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyEffectView.frame = blurEffectView.bounds
vibrancyEffectView.autoresizingMask = .FlexibleWidth | .FlexibleHeight
//Label for vibrant text
let vibrantLabel = UILabel()
vibrantLabel.text = "My Label"
vibrantLabel.textColor = UIColor(white: 0.64, alpha: 1)
vibrantLabel.textAlignment = .Center
vibrantLabel.sizeToFit()
vibrantLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
vibrancyEffectView.contentView.addSubview(vibrantLabel)
vibrancyEffectView.addConstraint(NSLayoutConstraint(item: vibrantLabel, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: vibrancyEffectView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 15))
vibrancyEffectView.addConstraint(NSLayoutConstraint(item: vibrantLabel, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: vibrancyEffectView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0))
vibrancyEffectView.addConstraint(NSLayoutConstraint(item: vibrantLabel, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: vibrancyEffectView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0))
vibrancyEffectView.addConstraint(NSLayoutConstraint(item: vibrantLabel, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: vibrantLabel, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 30))
blurEffectView.contentView.addSubview(vibrancyEffectView)
Could this be due to the autoresizing mask set on the parent, or is my auto layout constraints incorrect? Also I was wondering what is the best way to handle the height - I want to ensure the text fits it in.
I think a couple of your constraints are wrong.
You're pinning the bottom of the label to the bottom of the vibrancy view, with a constant of 15 - this will pin it 15 points below the bottom.
You're also pinning the height of the label to its own height plus 30 - this is unsatisfiable and I'm surprised you're not seeing error logs. A label doesn't need height constraints as it will have a intrinsic content size based on the text value - you also don't need the sizeToFit call. To make the label flow onto multiple lines, set the numberOfLines property to zero.
Type of constrains to be added for label.
left, top, width and height
TOP constrain(sample):
mylabel.setTranslatesAutoresizingMaskIntoConstraints(false)
self.addConstraint(NSLayoutConstraint(
item:mylabel, attribute:NSLayoutAttribute.Top,
relatedBy:NSLayoutRelation.Equal, toItem:myView,
attribute:NSLayoutAttribute.Bottom, multiplier:1.0, constant: 0.0))

Resources