Ignoring design time constraints set in IOS - ios

Lets say I have set a constraint for a label during design time and does not have any reference to those constraints to modify later. Lets assume that I set x and y position constraints during design time. When this control is being rendered, what if I set a different value for x and y by using frame.origin.x and frame.origin.y. Does this override the constraint I set in design time or constraint will win over this?

I don't really get what your understanding of a "design time constraint" is but here's the general mechanism how constraints work (and the behavior is all about your view's autoresizing mask setting):
translatesAutoresizingMaskIntoConstraints == false
⇒ Setting your views frame does not have any effect as it will be overridden by your constraints in the next layout pass.
translatesAutoresizingMaskIntoConstraints == true
⇒ Setting your view's frame adds several constraints behind the scenes the enforce that the view has the frame's size and position. However, it's important to know that in this case, you should not add any other constraints to the view as they will conflict with the "frame constraints".
If you want to understand the details, check out ▶️ this talk.
I also published an article on Medium not to long ago with very granular explanations on the autoresizing mask that is probably very relevant to your question (scroll to section Deactivating Auto Layout).
Note:
There is a way to have constraints only affect your layout at design time. You simply select the constraint in Interface Builder and check the Placeholder checkbox.
But from what I can tell it's not what you are talking about.

Related

How does "translatesAutoresizingMaskIntoConstraints" actually work?

I've recently taken up trying to learn how to create iOS applications completely programatically. And due to this, one of the first roadblocks I've encountered is that translatesAutoresizingMaskIntoConstraints must usually be set to false in order to set constraints.
After doing some research, there are three things that I am pretty sure of.
AutoresizingMasks are how dynamic layouts (layouts that differ based on screen size/orientation) were achieved prior to the introduction of the auto-layout system.
AutoresizingMasks are a value that tell a view's superview how to resize it when the superview's bounds change.
translatesAutoresizingMaskIntoConstraints is a boolean value that when set to true (and is always defaulted to true for code-created UIViews), tells the UIKit framework to create constraints that replicate the behavior of the AutoresizingMask property within the auto-layout system.
What I don't understand is how exactly these constraints are implemented. Apple states in their documentation that "the system creates a set of constraints that duplicate the behavior specified by the view’s autoresizing mask. This also lets you modify the view’s size and location using the view’s frame, bounds, or center properties..."
This is the part that confuses me, and I'm not sure if it's just their wording or my misunderstanding of the topic. The AutoresizingMask is just a value, so it doesn't make sense to be able to create constraints off of it. Do they mean that the automatically generated constraints are actually based off the child view's frame (A.K.A. childView.topAnchor = superview.topAnchor)? and that the AutoresizingMask's value just determines which of these constraints based on the frame gets set?
For example: UIView with frame of (x:0, y:0, width:50, height:50) and AutoresizingMask of "FlexibleBottomMargin". Does UIKit just automatically create constraints that place the view where a frame-based layout would have, and then leave out certain constraints (in this case the bottom) to replicate the mask's behavior?
You are correct that the autoresizingMask is interpreted (along with the frame) to determine which constraints to create.
In the example you give the system would create the following constraints -
Width constraint of 50
Height constraint of 50
Leading, trailing and top constraints to the nearest neighbours, with the fixed distance to those neighbours
Greater than or equal bottom constraint to the nearest neighbour with the distance to that neighbour.
This would result in a 50x50 view that was fixed horizontally and at the top and where the space between the bottom and its neighbour can grow as required.

In iOS, what's the difference between autoresizing, AutoLayout, and constraints?

In reading through the Apple documentation, I find references to autoresizing, AutoLayout, and constraints. What's the difference between using all of these in code? What is the correct way to apply these techniques programmatically in iOS 9?
There are really just two things here:
Autoresizing
AutoLayout
Autoresizing is basically a collective term for the old way Apple introduced in order to enable developers to build dynamic layouts. The number one usecase to address here was screen rotation. Since when a screen would be rotated (or otherwise resized), the subviews in the screen would most likely hold an incorrect frame (position and size) in the newly sized superview. To address this, Apple introduced a series of enumerable properties (called Autoresizing Masks), that tell the superview to treat a subview in a particular way. Among these are:
Flexible Width/Height, which causes a subview to expand to the fullest width/height available
Flexible Leading/Trailing/Top/Bottom space, which allows a specific edge to be variable, and so forth.
A view could contain any combination of these enum properties.
This was inadequate because, among other shortcomings, it lays down no rules regarding how a view should be layouted (if that's a verb) with respect to its other sibling views. It also required a lot of extra coding to manually resize views on orientation changes.
Here's where AutoLayout entered the picture. Apple built a framework which worked on the basis of constraints - rules that could be applied on views and between views, that would determine how a view would be sized in variable screen sizes. These constraints are structured in a class called NSLayoutConstraint, and each instance (constraint) of this class has the following important properties:
The item (view) on which the constraint is applied
The property of the view (height, width, leading edge, trailing edge, and so on) that the constraint is applicable to
The second item (a sibling or a child or a parent view) to which the constraint is related
The second item's attribute
The multiplier on the constraint: useful in order to specify ratio based constraints
A value (or constant) of the constraint: interestingly, the only property of a constraint that can be changed after instantiation.
A simple example of an NSLayoutConstraint, stated prosaically is: a view's width will be half the the width of its superview multiplied by 60%.
Your AutoLayout based UI would consist of many such constraints, which will all work together to express an unambiguous and non-conflicting UI Layout.
Now the AutoLayout engine, which makes it all work, interacts with views on the screen, calling AutoLayout messages such as layoutSubviews whenever needed in order automatically resize (layout) views whenever changes occur on screen, such as orientation change, a superview getting resized etc.
Constraints are most commonly added by InterfaceBuilder (.xib and .storyboard files), but adding them by code entails the same principle: create an instance of NSLayoutConstraint and add it to the highest view applicable (for eg., if there's a constraint between a child and a parent view, the constraint should be added to the parent view. If there's a constraint between two subviews, again, add it to the parent.)
Apple's AutoLayout guides, API documentation and introductory WWDC videos on AutoLayout are excellent, and those would be the best places to learn more.

Update Frames & Constraints in Xcode (Interface Builder)

I have been learning Xcode and iOS and things are going well with coding but I am confused about a few options in interface builder.
It seems that when I add a contraint I can choose to "Update Frames" and then either "Items of new contraints" or "All Frames" but it seems that I don't always need to do this... sometimes I do and sometimes I don't - I don't think I truly understand the concept. It seems to be optional. When is the case to choose it or not?
Once a constraint is added, then should that be it?
There is also a context menu (Resolve autolayout issues) (3rd item on the bottom on interface builder, represented by a triangle between 2 vertical lines) which also allows me to Force Update of constraint or update of frame. Why is this needed ? I notice the options inside are usually disabled so I presume this becomes active when there are issues ?
I have tried searching the internet and I can't find anything specific; the more I read, the more confused I seem to get.
Also, a sanity check: a frame is the bounding box of every single control (view) not just the viewcontrol, so every view (control) as its own frame. Is this correct?
I'll try to explain the concept of constraints and storyboard representation.
Constraints - are used to determine the position of UIView elements inside your view. For example, the vertical distance from top of the view to UIView element top. When you add constraint using the storyboard it plays 2 roles:
Positioning the element inside a view when your app runs
Positioning the element in the storyboard representation itself
Update Frames - is used when you want to update storyboard display so that it fits the currently applied constraints. When the display of the storyboard does not match the constraints a warning will appear.
Add missing constraints / Update constraints - will create/change the constraints applied on UIView element to match what currently presented in the storyboard. Kind of the other way around from update frames.
This answer is not a replacement for Apple's Auto Layout Guide
You do not have to click on "update frame" every time you add a constraint, if you do, it will update the frame of the view to whatever it should be based on the constraints. Yes, every view has a frame and it is the rectangle relative to the views superview.
More often than not you'll probably click on update constraints (Shift + Command + =), this will allow you to resize views that are already constrained, and have the constraints updated to match.

Can you add a derived constraint using auto layout?

In mechanical CAD software which uses concepts similar to autolayout constraints, you can often add a 'derived constraint'. This has no effect on the layout, but will allow you to directly read the value of an important dimension.
For example, consider the following layout for a view with two subviews:
32 64
|------| |------|
|-[imgOne]-[imgTwo]-|
|-------------------|
w
The width of the view is the sum of the default edge spacing on the left and right, the default spacing between image views, and the two width constraints (32 and 64) applied to the image views.
I would like to know w at runtime.
In theory, this should be view.bounds. However, it's not always safe to read that property (as the view may not have updated its layout constraints yet).
Is it possible to add a constraint which has no effect on the view size, but which will have its .constant property updated once the layout is complete?
(I have tried adding a width constraint to the view with a priority of 1, but .constant always reads the nominal value, instead of the actual value.)
Adding a "derived" constraint will put you in the same hole you began in--waiting for Auto Layout to finish laying out your views. It's all about timing. When using Auto Layout, a good place to read the final geometries of your views is in your view controller's viewDidLayoutSubviews method. In other words, read the bounds of the view in viewDidLayoutSubviews.

How do you balance Auto Layout with creating frames?

When I'm creating a frame in iOS with CGRectMake(), be it setting the frame property or using initWithFrame:, it asks for the x, y, width and height. I supply these.
But with Auto Layout, I'm next going to say something like: "position its x in the very middle" and "set the width to half the screen", right after I set those with CGRectMake() likely differently.
What do I set them as in CGRectMake()? 0? An arbitrary value? Something close to what I want?
When using auto-layout, you shouldn't set the frame property at all. You can set the frame, but there's no purpose in doing so, and only makes your code misleading as the frame will be superseded by the dimensions it calculates from the constraints. I would suggest completely defining the dimensions of the controls using constraints and avoid setting the frame entirely to avoid confusion.
So, if you're creating views programmatically, instead of initWithFrame, just do init. Also, do not forget to set translatesAutoresizingMaskIntoConstraints to NO, and add all of the appropriate constraints such that the layout is unambiguous, but with no conflicting constraints, either.

Resources