Updating constraint dynamically not working - ios

I'm facing one issue while updating top constraint dynamically.
I have one subview1 added over viewcontroller1 view in its xib file and i have given topview constraint to subview1 as 65 and created an outlet for it.
Now i have added viewcontroller1 view over viewcontroller2. After adding it i'm trying to update the constant value of the constraint to 108. But its not getting reflected.
In viewcontroller1 i'm doing
self.topErrorViewConstarints.constant = 108
self.view.updateConstraints()
Any idea why its not getting reflected?

You need to layout the view again.
self.view.layoutIfNeeded()

Try this:
self.topErrorViewConstarints.constant = 108
self.view.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
It should work. If not then you made mistake somewhere else.

That's not how updateConstraints() supposed to work.
You can, of course, modify any constraints then update layout like this:
self.topErrorViewConstarints.constant = 108
self.view.layoutIfNeeded()
But if you want to implement updateConstraints() you need the following:
// Call when you need to update your custom View
self.view.setNeedsUpdateConstraints()
Then inside the View override the function which will be called automatically by the system:
override func updateConstraints() {
super.updateConstraints()
topErrorViewConstarints.constant = currentTopErrorConstraint()
}
So, updateConstraints() is better suited for custom views with inner layout, that you don't want to be modified from outside. Also, it's good when you need to update many constraints at once.

Problem:
I have faced a similar problem in UiKit code. I created a view programmatically and the add constraint like below:
myView?.heightAnchor.constraint(equalToConstant: oldValue).isActive = true
It worked fine for the first time when the view is created. But need to update the height for some events, so I did like this:
myView?.heightAnchor.constraint(equalToConstant: oldValue).isActive = false
myView?.heightAnchor.constraint(equalToConstant: newValue).isActive = true
But the newValue had no effect, I also try with:
parentOfMyView.layoutIfNeeded()
It was also a failed attempt.
Solution:
I created a global variable to store the constraint:
private var viewHeightAnchor: NSLayoutConstraint?
Then use that when needed:
viewHeightAnchor?.isActive = false
viewHeightAnchor = myView?.heightAnchor.constraint(equalToConstant: 80.0)
viewHeightAnchor?.isActive = true
In this way I also didn't have to call layoutIfNeeded()

Related

Button in tip view create by EasyTipView

I'm using EasyTipView to create a custom tip view have a button inside look like the image below. But notthing happen when I click to button inside tip view. Does anyone have use this libray and know how to fix this problem ?
My demo: github.com/minhtien1403/TestTipView
Library link: https://github.com/teodorpatras/EasyTipView
View hierarchy is fine, nothing overlay the button
As from your github demo, I notice things make button click inside not working.
First of all, in your CustomTipView when ever you change to position, you call translatesAutoresizingMaskIntoConstraints to redefine view which make the xib not working correctly anymore. Just need to remove this
fileprivate func arrange(withinSuperview superview: UIView) {
// your others code
if case .view(let contentView) = content {
contentView.translatesAutoresizingMaskIntoConstraints = false // remove this
contentView.frame = getContentRect(from: getBubbleFrame())
}
// your others code
}

The proper way to inherit a CustomViewController with "dependencies"

Recently I wrote an app with one single scene and ViewController. I had to set a custom background picture for the View, which the ViewController manages (i.e. my top view contained the UIImageView). Later on I had to implement some logic in ViewController, so that it properly rotates/changes the picture when the screen is rotated. Also I had to overwrite some properties like preferredStatusBarStyle for the ViewController.
Now I have to implement a couple more scenes / screens in my app and it turns out that they all must have the same design as this currently present screen, so I think it makes sense if I create a CommonViewController which contains this common rotation-related logic for background picture, so that I can inherit all my other ViewControllers from this CommonViewController. The only problem I have is that CommonViewController "requires" that the view it manages has a backgroundPicture: UIView property, which I don't know how to ensure.
If I create a new file CommonViewController together with XIB-file, I can add the backgroundPicture image view in XIB and connect it with code (via regular "control-drag" approach), but apparently this won't work, as there is no guarantee that the views which inherit CommonViewController will have this property. What is the correct way to solve this issue without hacks on iOS in Swift?
Unfortunately I could not find a solution, maybe I've been searching for something wrong. It seems that I somehow need to inherit a CommonViewController for each scene (for each CustomViewController), but also I have to somehow set the top view of each of these controller's to be equal to some CommonView, so that CommonViewController does not crash when I try to access #IBOutlet weak var backgroundPicutre: UIImageView!.
The obvious way would be to define some method or property in the CommonViewController, so that the controllers which inherit it, can implement / override it, but it seems a bit hacky as it still requires copy-pasting in each ViewController which inherits CommonViewController.
How I imagined the solution: I create CustomViewController: CommonViewController, then I create a view controller in my Storyboard and change the "Class" property to "CustomViewController" (in property editor), then I select the view which corresponds to this newly added controller and change the "Class" property to "BackgroundImageView. But I'm not sure if it's the correct way to do (also I doubt thatCustomViewControllerwill properly "connect" itsIBOutletfieldbakcgroundImageViewwith the correspondingUIViewfromBackgroundImageView`, that's why I wanted to ask experts what they think about it.
I think you should define your base controller (CommonViewController) entirely in code, i.e. don't use no xibs / storyboards for the base controller. It doesn't mean you should rid off storyboards / xibs completely. Interface for alll other view controllers except CommonViewController may still be implemented with xibs / storyboards.
In this case CommonViewController implementation may look like this:
import UIKit
class CommonViewController: UIViewController {
// use this property every time you need to
// manipulate backgroundPicture
var backgroundPicture: UIImageView = {
// Replace with your image name
let image = UIImage(named: "BackgroundPicture")!
let imageView = UIImageView()
imageView.image = image
return imageView
}()
override func viewDidLoad() {
// If subclass overrides viewDidLoad()
// it should contain super.viewDidLoad()
super.viewDidLoad()
view.addSubview(backgroundPicture)
// Align backgroundPicture to bounds of superview
// You can remove this code and implement
// your own alignment with frames or Autolayout
backgroundPicture.frame = view.bounds
// Send backgroundPicture to back of the view
// Otherwise backgroundPicture may overlap views added in subclasses
view.sendSubviewToBack(backgroundPicture)
}
override func viewDidLayoutSubviews() {
// If subclass overrides viewDidLayoutSubviews()
// It should contain super.viewDidLayoutSubviews()
super.viewDidLayoutSubvews()
// Align backgroundPicture to bounds of superview
// You can remove this code and implement
// your own alignment with frames or Autolayout
backgroundPicture.frame = view.bounds
}
}

Why calling setNeedsUpdateConstraints isn't needed for constraint changes or animations?

Readings:
From this answer:
This is what the accepted answer suggests to animate your view changes:
_addBannerDistanceFromBottomConstraint.constant = 0
UIView.animate(withDuration: 5) {
self.view.layoutIfNeeded()
}
Why do we call layoutIfNeeded when we aren't changing the frames. We are changing the constraints, so (according to this other answer) shouldn't we instead be calling setNeedsUpdateConstraints?
Similarly this highly viewed answer says:
If something changes later on that invalidates one of your
constraints, you should remove the constraint immediately and call
setNeedsUpdateConstraints
Observations:
I actually did try using them both.
Using setNeedsLayout my view animates correctly to the left
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func animate(_ sender: UIButton) {
UIView.animate(withDuration: 1.8, animations: {
self.centerXConstraint.isActive = !self.centerXConstraint.isActive
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
})
}
#IBOutlet weak var centerYConstraint: NSLayoutConstraint!
#IBOutlet var centerXConstraint: NSLayoutConstraint!
}
However using setNeedsUpdateConstraints doesn't animate, It just moves the view rapidly to the left.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func animate(_ sender: UIButton) {
UIView.animate(withDuration: 1.8, animations: {
self.centerXConstraint.isActive = !self.centerXConstraint.isActive
self.view.setNeedsUpdateConstraints()
self.view.updateConstraintsIfNeeded()
})
}
#IBOutlet weak var centerYConstraint: NSLayoutConstraint!
#IBOutlet var centerXConstraint: NSLayoutConstraint!
}
If I don't want animation then using either of view.setNeedsLayout or view.setNeedsUpdateConstraints move it to the left. However:
with view.setNeedsLayout, after my button is tapped, my viewDidLayoutSubviews breakpoint is reached. But the updateViewConstraints breakpoint is never reached. This leaves me baffled as to how the constraints are getting updated...
with view.setNeedsUpdateConstraints, after the button is tapped my updateViewConstraints breakpoint is reached and then the viewDidLayoutSubviews breakpoint is reached. This does make sense, the constraints are updated, then the layoutSubviews is called.
Questions:
Based on my readings: if you change constraints then for it to become effective you MUST call setNeedsUpdateConstraints, but based on my observations that's wrong. Having the following code was enough to animate:
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
WHY?
Then I thought maybe somehow under the hoods it's updating the constraints through other means. So I placed a breakpoint at override func updateViewConstraints and override func viewDidLayoutSubviews but only the viewDidLayoutSubviews reached its breakpoint.
So how is the Auto Layout engine managing this?
This is a common misunderstanding among iOS developers.
Here's one of my "golden rules" for Auto Layout:
Don't bother about "updating constraints".
You never need to call any of these methods:
setNeedsUpdateConstraints()
updateConstraintsIfNeeded()
updateConstraints()
updateViewConstraints()
except for the very rare case that you have a tremendously complex layout which slows down your app (or you deliberately choose to implement layout changes in an atypical way).
The Preferred Way to Change Your Layout
Normally, when you want to change your layout, you would activate / deactivate or change layout constraints directly after a button tap or whichever event triggered the change, e.g. in a button's action method:
#IBAction func toggleLayoutButtonTapped(_ button: UIButton) {
toggleLayout()
}
func toggleLayout() {
isCenteredLayout = !isCenteredLayout
if isCenteredLayout {
centerXConstraint.isActive = true
} else {
centerXConstraint.isActive = false
}
}
As Apple puts it in their Auto Layout Guide:
It is almost always cleaner and easier to update a constraint immediately after the affecting change has occurred. Deferring these changes to a later method makes the code more complex and harder to understand.
You can of course also wrap this constraint change in an animation: You first perform the constraint change and then animate the changes by calling layoutIfNeeded() in the animation closure:
#IBAction func toggleLayoutButtonTapped(_ button: UIButton) {
// 1. Perform constraint changes:
toggleLayout()
// 2. Animate the changes:
UIView.animate(withDuration: 1.8, animations: {
view.layoutIfNeeded()
}
}
Whenever you change a constraint, the system automatically schedules a deferred layout pass, which means that the system will recompute the layout in the near future. No need to call setNeedsUpdateConstraints() because you just did update (change) the constraint yourself! What needs to be updated is the layout i.e. the frames of all your views, not any other constraint.
The Principle of Invalidation
As previously stated, the iOS layout system usually doesn't react immediately to constraint changes but only schedules a deferred layout pass. That's for performance reasons. Think of it like this:
When you go shopping groceries, you put an item in your cart but you don't pay it immediately. Instead, you put other items in your cart until you feel like you got everything you need. Only then you proceed to the cashier and pay all your groceries at once. It's way more efficient.
Due to this deferred layout pass there is a special mechanism needed to handle layout changes. I call it The Principle of Invalidation. It's a 2-step mechanism:
You mark something as invalid.
If something is invalid, you perform some action to make it valid again.
In terms of the layout engine this corresponds to:
setNeedsLayout()
layoutIfNeeded()
and
setNeedsUpdateConstraints()
updateConstraintsIfNeeded()
The first pair of methods will result in an immediate (not deferred) layout pass: First you invalidate the layout and then you recompute the layout immediately if it's invalid (which it is, of course).
Usually you don't bother if the layout pass will happen now or a couple of milliseconds later so you normally only call setNeedsLayout() to invalidate the layout and then wait for the deferred layout pass. This gives you the opportunity to perform other changes to your constraints and then update the layout slightly later but all at once (→ shopping cart).
You only need to call layoutIfNeeded() when you need the layout to be recomputed right now. That might be the case when you need to perform some other calculations based on the resulting frames of your new layout.
The second pair of methods will result in an immediate call of updateConstraints() (on a view or updateViewConstraints() on a view controller). But that's something you normally shouldn't do.
Changing Your Layout in a Batch
Only when your layout is really slow and your UI feels laggy due to your layout changes you can choose a different approach than the one stated above: Rather than updating a constraint directly in response to a button tap you just make a "note" of what you want to change and another "note" that your constraints need to be updated.
#IBAction func toggleLayoutButtonTapped(_ button: UIButton) {
// 1. Make a note how you want your layout to change:
isCenteredLayout = !isCenteredLayout
// 2. Make a note that your constraints need to be updated (invalidate constraints):
setNeedsUpdateConstraints()
}
This schedules a deferred layout pass and ensures that updateConstraints() / updateViewConstraints() will be called during the layout pass. So you may now even perform other changes and call setNeedsUpdateConstraints() a thousand times – your constraints will still only be updated once during the next layout pass.
Now you override updateConstraints() / updateViewConstraints() and perform the necessary constraint changes based on your current layout state (i.e. what you have "noted" above in "1."):
override func updateConstraints() {
if isCenteredLayout {
centerXConstraint.isActive = true
} else {
centerXConstraint.isActive = false
}
super.updateConstraints()
}
Again, this is only your last resort if the layout is really slow and you're dealing will hundreds or thousands of constraints. I have never needed to use updateConstraints() in any of my projects, yet.
I hope this make things a little clearer.
Additional resources:
Auto Layout – From Leading to Trailing: my talk from UIKonf 2017, topics:
"The Layout Pass" and
"Updating Constraints"
The Auto Layout Comprehendium™: scroll down to section "Updating Constraints", maintained by me
The Auto Layout Guide by Apple: sections
"Changing Constraints"
"The Deferred Layout Pass"
I will try to explain it simply:
The first thing to remember is that updating constraints does not cause the layout of views to be updated immediately. This is for performance reasons as laying everything out can take time so it 'makes note' of changes that need to take place then does a single layout pass.
Taking that one step further you can then not even update constraints when something affecting them changes but just flag that the constraints need to be updated. Even updating the constraints themselves (without laying out the views) can take time and the same ones could change both ways (i.e. active and inactive).
Now considering all that what setNeedsUpdateConstraints() does is to flag that the constraints for a view need to be re-calculated BEFORE the next layout pass because something about them has changed it doesn't make any constraint changes of affect the current layout at all. Then you should implement your own version of the updateConstraints() method to actually make the required changes to the constraints based on the current app state, etc.
So when the system decides the next layout pass should occur anything that has had setNeedsUpdateConstraints() called on it (or the system decides needs updating) will get its implementation of updateConstraints() called to make those changes. This will happen automatically before the laying out is done.
Now the setNeedsLayout() and layoutIfNeeded() are similar but for control of the actual layout processing itself.
When something that affects the layout of a view changes you can call setNeedsLayout() so that that view is 'flagged' to have it's layout re-calculated during the next layout pass. So if you change constraints directly (instead of perhaps using setNeedsUpdateConstraints() and updateConstraints()) you can then call setNeedsLayout() to indicate that the views layout has changed and will need to be re-calculated during the next layout pass.
What layoutIfNeeded() does is to force the layout pass to happen then and there rather than waiting for when the system determines it should next happen. It's that the forces the re-calculation of the layouts of views based on the current sate of everything. Note also that when you do this fist anything that has been flagged with setNeedsUpdateConstraints() will first call it's updateConstraints() implementation.
So no layout changes are made until the system decides to do a layout pass or your app calls layoutIfNeeded().
In practice you rarely need to use setNeedsUpdateConstraints() and implement your own version of updateConstraints() unless something is really complex and you can get by with updating view constraints directly and using setNeedsLayout() and layoutIfNeeded().
So in summary setNeedsUpdateConstraints doesn't need to be called to make constraint changes take affect and in fact if you change constraints they will automatically take affect when the system decides it's time for a layout pass.
When animating you want slightly more control over what is happening because you don't want an immediate change of the layout but to see it change over time. So for simplicity let's say you have an animation that takes a second (a view moves from the left of the screen to the right) you update the constraint to make the view move from left to right but if that was all you did it would just jump from one place to another when the system decided it was time for a layout pass. So instead you do something like the following (assuming testView is a sub view of self.view):
testView.leftPositionConstraint.isActive = false // always de-activate
testView.rightPositionConstraint.isActive = true // before activation
UIView.animate(withDuration: 1) {
self.view.layoutIfNeeded()
}
Let's break that down:
First this testView.leftPositionConstraint.isActive = false turns off the constraint keeping the view in the left hand position but the layout of the view is not yet adjusted.
Second this testView.rightPositionConstraint.isActive = true turns on the constraint keeping the view in the right hand position but again the layout of the view is not yet adjusted.
Then you schedule the animation and say that during each 'time slice' of that animation call self.view.layoutIfNeeded(). So what that will do is force a layout pass for self.view every time the animation updates causing the testView layout to be re-calculated based on it's position through the animation i.e. after 50% of the animation the layout will be 50% between the stating (current) layout and the required new layout.
Thus doing that the animation takes affect.
So in overall summary:
setNeedsConstraint() - called to inform the system that the constraints of a view will need to be updated because something affecting them has changed. The constraints are not actually updated until the system decides a layout pass is needed or the user forces one.
updateConstraints() - this should be implemented for views to update the constraints based on the apps state.
setNeedsLayout() - this informs the system that something affecting the layout of a view (constraints probably) have changed and the layout will need to be re-calculated during the next layout pass. Nothing happens to the layout at that time.
layoutIfNeeded() - performs a layout pass for the view now rather than waiting for the next system scheduled one. At this point the view and it's sub views layouts will actually be re-calculated.
Edit to hopefully more directly answer the two questions:
1) Based on my readings: if you change constraints then for it to become effective you MUST call setNeedsUpdateConstraints, but based on my observations that's wrong. Having the following code was enough to animate:
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
WHY?
First you have misunderstood in your readings you don't need to use setNeedsUpdateConstraints at all. Secondly they are enough (assuming they are in an animation block) because the setNeedsLayout() flags that self.view needs to have it's layout (and therefore its sub views layouts) re-calculated and the 'layoutIfNeeded()' forces the layout to take place immediately and therefore if inside an animation block to be done at each update of the animation.
2) Then I thought maybe somehow under the hoods it's updating the constraints through other means. So I placed a breakpoint at override func updateViewConstraints and override func viewDidLayoutSubviews but only the viewDidLayoutSubviews reached its breakpoint.
So how is the Auto Layout engine managing this?
Best to show with your original example of this:
_addBannerDistanceFromBottomConstraint.constant = 0
UIView.animate(withDuration: 5) {
self.view.layoutIfNeeded()
}
The first line has updated the constraint by changing its constant (no need to use setNeedsUpdateConstraints) but the layout of the view (i.e. it's actual frame position and size) has not yet changed. When you call self.view.layoutIfNeeded() within the animation block that updates the layout of self.view which based on the current time frame of the animation. It is at this point that the frame position/size of views is calculated and adjusted.
I hope that makes it clearer but in reality your questions have been answered in detail in the body of the question maybe it was too detailed of an explanation though.
Now to help clarity EVERY view on the screen has a frame controlling both its size and position. This frame is either set manually via the property or is calculated using the constraints you have setup. Regardless of the method it's the frame that determines the position and size of the view not the constraints. The constraints are just used to calculate the frame of a view.
To try to make it even clearer I will now add two examples that achieve the same thing but using the two different methods. For both there is a testView which has constraints putting it in the centre of the main view controller view (these won't be changing and can effectively be ignored for the example). There is also a widthConstraint and a heightConstraint for that testView which will be used to control the height and width of the view. There is an expanded bool property which determines whether the testView is expanded or not and a testButton which is used to toggle between expanded and collapsed states.
The first way of doing it is this:
class ViewController: UIViewController {
#IBOutlet var testView: UIView!
#IBOutlet var testButton: UIButton!
#IBOutlet var widthConstraint: NSLayoutConstraint!
#IBOutlet var heightConstraint: NSLayoutConstraint!
var expanded = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func testButtonAction(_ sender: Any) {
self.expanded = !self.expanded
if self.expanded {
self.widthConstraint.constant = 200
self.heightConstraint.constant = 200
} else {
self.widthConstraint.constant = 100
self.heightConstraint.constant = 100
}
self.view.layoutIfNeeded() // You only need to do this if you want the layout of the to be updated immediately. If you leave it out the system will decide the best time to update the layout of the test view.
}
}
and here when the button is tapped the expanded bool property is toggled and then the constraints are immediately updated by changing their constants. layoutIfNeeded is then called to re-calculate the layout of the testView immediately (thus updating the display) although this could be left out leaving the system to re-calculate the layout based on the new constraint values when it needs to.
Now here is another way of doing the same thing:
class ViewController: UIViewController {
#IBOutlet var testView: UIView!
#IBOutlet var testButton: UIButton!
#IBOutlet var widthConstraint: NSLayoutConstraint!
#IBOutlet var heightConstraint: NSLayoutConstraint!
var expanded = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func testButtonAction(_ sender: Any) {
self.expanded = !self.expanded
self.view.setNeedsUpdateConstraints()
}
override func updateViewConstraints() {
super.updateViewConstraints()
if self.expanded {
self.widthConstraint.constant = 200
self.heightConstraint.constant = 200
} else {
self.widthConstraint.constant = 100
self.heightConstraint.constant = 100
}
}
}
and here when the button is tapped the 'expanded' bool property is toggled and we use updateConstraintsIfNeeded to flag to the system that the constraints will need to be updated before the layout can be re-calculated (whenever it may be the system determines that is needed). When the system needs to know those constraints to re-calculate the layout of the views (something it decides) it automatically calls updateViewConstraints and the constraints are changed at this time to their new values.
So if you try it these both do fundamentally the same thing as they stand but there are different use cases for them.
Using method 1 allows animation because (as has been noted) you can wrap the layoutIfNeeded in an animation block like this:
UIView.animate(withDuration: 5) {
self.view.layoutIfNeeded()
}
which causes the system to animate between the initial layout and the new layout based on the constraint changes since the last time the layout was calculated.
Using method 2 allows you to postpone the need to change constraints until they are absolutely needed and you would want to do this when your constraints are really complex (lots of them) or there could be lots of actions that happen that could require the constraints to be changed before the next layout re-calculation is needed (to avoid continually changing constraints when not needed). Doing this though you lack the ability to animate the changes but that's probably not an issue as the complexity of the constraints would make everything slow to a crawl anyway.
I hope this helps more.
setNeedsUpdateConstraints will update the constraints that will be changed based on a change you have made. For example if your view has a neighboring view with which there a constraint of horizontal distance, and that neighbor view got removed, the constraint is invalid now. In this case you should remove that constraint and call setNeedsUpdateConstraints. It basically makes sure that all your constraints are valid. This will not redraw the view. You can read more about it here.
setNeedsLayout on the other hand marks the view for redrawing and putting it inside animation block makes the drawing animated.

How to create multiple UIViews using the same function

I would like to create multiple UIViews that can be reproduced by using a single function. I have a UIView that is placed on a storyboard and connected to my class with an IBOutlet:
#IBOutlet weak var contentView: UIView!
I have a function that loads a xib into my UIView:
func createView(layoutConstant: CGFloat) {
if let customView = NSBundle.mainBundle().loadNibNamed("TestView", owner: self, options: nil).first as? TestView {
contentViewTopLayoutConstraint.constant = layoutConstant
contentView.addSubview(customView)
}
}
I am now trying to add two of them to my view, but only one shows up:
createView(0)
createView(70)
Any ideas?
I think both views are added, although they happen to be in the same spot, so it looks like there is only one! A quick and dirty way to verify that would be updating your createView method with this line:
contentView.frame.origin.y = layoutConstant
Basically your contentViewTopLayoutConstraint is not connected to the views you are creating, so setting its constant value will not have any impact.
Because frames for all those views will of same size. Origin(x,y) will be same for all the views, so they are overlapping one on another and you can only see the top one view.
In your code example it looks like you're only setting a layout constraint on the contentView you are placing your two new views inside of. What you need to do is set layout constraints on the two views your are placing inside in relation to their superview i.e. the contentView.
Basically, add the layout constraints to the customView views.
its quite simple.. iterate a loop by creating uiview along with adding those into the array and customize your particular view by getting them using array index.
Happy code ..

Can't set translatesAutoresizingMaskIntoConstraints

In an attempt to solve an Auto-Layout issue related to programmatically adding sub views to a scroll view, I have run into many references throughout the internet that, in various scenarios say to set translatesAutoresizingMaskIntoConstraints = YES or translatesAutoresizingMaskIntoConstraints = NO, depending on the case.
However, in Swift, when I type:
var view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
I get the in-line error: Cannot assign to 'translatesAutoresizingMaskIntoConstraints' in 'view'. Why? Because, when inspected, you'll find that it's a parameterless function, not a property.
I've gotten around this by subclassing, but it's a major inconvenience to have to subclass every view I'm dealing with, just to set translatesAutoresizingMaskIntoConstraints:
class CardView: UIView {
override func translatesAutoresizingMaskIntoConstraints() -> Bool {
return false
}
}
Does anyone know a way around this, or can shed light on the discrepancy between what the general internet councils tell you and what you can actually do, in Swift?
translatesAutoresizingMaskIntoConstraints is actually a method on UIView and not a property.
The syntax works because ObjC lets you use dot-notation for calling methods as well (there's a whole other discussion on how properties actually auto-generate getter/setter methods).
Use the method instead of trying to use the property notation from ObjC
view.setTranslatesAutoresizingMaskIntoConstraints(false)
Use view.setTranslatesAutoresizingMaskIntoConstraints(false) instead.
Swift 2
view.translatesAutoresizingMaskIntoConstraints = false
If you create any views in code like text views, buttons, labels, etc.
You need to be careful how you add Auto Layout constraints to them. The reason for this is that iOS creates constraints for you that match the new view's size and position, and if you try to add your own constraints these will conflict and your app will break.
Lets take an example for a uilabel:
let titleLabel = UILabel()
titleLabel.translatesAutoresizingMaskIntoConstraints = false
Likewise in your case:
let newView = UIView(frame: CGRectZero)
addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false

Resources