Archives for October 2014

Auto Layout Advanced Techniques for iOS 8 and 7 using XCode 6 on Storyboard

As promised from a previous post (How to Use Auto Layout in XCode 6 for iOS 7 and 8 Development) that I will write another article related to more advanced techniques in AutoLayout to develop iOS mobile apps for iOS 7 and iOS 8.

In this article, I am going to share a few common layouts, scenarios and problems that I am facing when I am developing the iOS app using the Auto Layout. I am going to show the techniques to link different objects together using constraints inside the same view controller.

Auto Layout for iOS 8 versus iOS 7

I believe most iOS developers will still include iOS 7 under their development plan. So before getting started, it is good to know the differences between Autolayout in iOS 7 compare with iOS 8.

One of new things in iOS 8 is the Layout Margin. Layout Margin is a new property available in UIView for iOS 8. So, any objects inherit from UIView will have this property. If you are developing the app for both iOS 7 and iOS 8, you should not use Layout Margin (or use layout margin in a smart way).

So, if you have any constraints related to layout margin and you didn’t do a proper check before launching the app on iOS 7 devices, the app might crash or the arrangement of the objects might be out of order.

Whenever you are trying to add new constraints from the storyboard in XCode 6, “Constrain to Margins” is ticked by default as show as the screen shot below. The meaning of this selection is to add constraints with the new property in iOS 8.

Constrain to Margins iOS 8

If the deployment target of your app is iOS 7 and above and any of your constraints have this layout margin, the XCode will complain with the warning “Layout attributes relative to the layout margin on iOS prior to 8.0”.

Layout attributes relative to the layout margin on iOS prior to 8.0 warning

If you are developing the app for both iOS 7 and 8, it is best to “Untick” the Constrain to Margins.

How to use Auto Layout with more than One Object

Using the autolayout constraints with more than one object inside the same view controller can be tricky.

You may ask yourself some questions when you are deciding the design before trying to link the objects together inside the view controller:-
1. How many objects are inside the view controller?
2. Is the object fixed in height or have flexible height?
3. Is the object fixed in width or have flexible width?
4. How would the object be positioned inside the view controller. (Eg: Stick on the top of the view controller)
5. What is the relationship between Object A and object B? (eg: The Object B is positioned on the Right of the Object A)

Example:-
Let’s say I have a view controller with 2 Text Fields (Email and Password) and one Login Button.

Here is my decision:-
1. Both the Text Fields have fixed height (50 px) but with flexible width.
2. There will be a Navigation Controller on the top of the View Controller.

Decision on EmailTextField
– The Top of the First Text Field (EmailTextField) will stick to the Top Layout Guide of the Navigation Controller
– The Left of the EmailTextField will stick to the Left Side of the Superview (Leading Space)
– The Right of the EmailTextField will stick to the Right Side of the Superview (Trailing Space)

So, there are 4 constraints that I will have to associate with this EmailTextField object. The below screen shot shows the 4 constraints:-

Auto Layout with more than One Object1

If you do it correctly, You will see 4 constraints on the Size Inspector and also the Document Outline like the screen shot below.

Auto Layout with more than One Object2

Next, I want to add the PasswordTextField onto the screen. I will position it on the bottom of the EmailTextField.

Decision on PasswordTextField
– The Top of the First Text Field (EmailTextField) will stick to the Bottom of the EmailTextField.
– The Left of the PasswordTextField will stick to the Left Side of the Superview.
– The Right of the PasswordTextField will stick to the Right Side of the Superview.

Here is screen shot for adding the constraints for the PasswordTextField.
Auto Layout with more than One Object3

If you do it correctly, you will see that the Top Space of the PasswordTextField is Linked to the Bottom Space of the EmailTextField like the screen shot below:-
Auto Layout with more than One Object4

IMPORTANT TIP: Double Click on the constraint on the Size Inspector to view the detailed relationship of the constraint.

Finally, let’s link the constraints for the last object – the login button.

Decision on the Login Button
– The button has fixed height: 60 px
– It will stick on the bottom of the view controller with constant: 20 px (distance)
– There will be constant 16 px on the Left and Right of the superview
Auto Layout with more than One Object5

The above auto layout guide for multiple objects inside the same view controller is very straight forward because the top objects (EmailTextField,PasswordTextField) does not have any relationship with the bottom object (Login Button).

The autolayout will become more complicated when you want to add a UIScrollView and links all the objects together.

How to use UIScrollView with Auto Layout

Using the Auto Layout with UIScrollView can be tricky. I personally having a tough time with ScrollView when I first started learning Auto Layout. After some trials and errors for a few weeks, I almost got it right.

The most basic rule of using ScrollView with Auto Layout is you will have to set up the constraints from the top of the ScrollView to the bottom of the Scrollview and from the left to the Right. You can not have any missing link neither the horizontal nor the vertical layout. Or else the XCode will complaint!

Let’s just use the same example as the above and we will add all the 3 objects inside the UIScrollView.

First of all, we will have to add the scrollview onto the empty View Controller inside the Storyboard. For my personal preference, I would stick the top of the ScrollView on the top layout guide and not under the UINavigationBar. Remember, the Scrollview will always have flexible height and flexible width.

Autolayout with Scrollview1

If you do it correctly, you will see that the leading and the trailing space to the super view will be 0, the bottom space to the bottom layout guide is 0 and also the top space to the top layout guide would be 0 as well like screen shot below:-
Autolayout with Scrollview2

Next, putting the 2 text fields and also the login button inside the scrollview. If I connect the constraints exactly like the first example that I showed above. The XCode will complaint. The reason is adding a scrollview will change the behaviour of the Autolayout.

The common complaints:

1. Frame for “XXX” will be different during run time.
To Solve it: Add another constraint to align the object to the center of the superview (ScrollView)

Autolayout with Scrollview3

Autolayout with Scrollview4

2. The Views are vertically ambiguous or (Scroll View has Ambiguous scrollable content height)
To solve it: Link the objects from the top to the Bottom of the Scrollview (No missing relationship in the middle)

For the above case, I will make another constraint (Horizontal Center in Contrainer) to centrelize the EmailTextField. And then “Control Drag” to link up PasswordTextField with LoginButton with a vertical space.

Autolayout with Scrollview5

The XCode will love you by adding the 2 extra constraints and stop complaining.

How to Resolve Conflict Constraints and Other Autolayout Errors/Warning

Here are some of the common AutoLayout Errors/Warnings:-

Warning #1: Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0

Description: This only happens when your app has to support iOS 7 and the app have UILabel on one of your View Controller Objects inside the storyboard. And you didn’t tick “Explicit” on the “Preferred Width”.

How to Resolve this issue?
A. If you know where to locate the specific UILabel, just select the UILabel Object on the Storyboard. Then, Make sure that “Explicit” is ticked. If you do not want to have a fixed width, just assign the value as 0 (zero). The width for the UILabel will be based on the other connected constraints for this UILabel.
Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0

B. When your storyboard has many view controllers objects and also many UILabel, you may find it hard to locate the specific UILabel object. So, you will have to use the following steps in order to location the UILabel.

Resolve the Automatic Preferred Max Layout Width Warning From SourceCode

1. Right Click the Storyboard and “Open As” -> “Source Code”

2. Use the keyboard Key (Command + F) or Click “Find” -> “Find” on the Navigation bar of the XCode to launch the Search Window. Paste the code

into the Find Window.
3. Click the Search Icon then Select “Edit Find Options”.

4. Then, Choose “Regular Expression”.

5. The Find Window will show you all the UILabel does not have preferred Layout Width. You will have to paste

into all the UILabel like below screen shot until the count for the Find Window is 0.

6. Lastly, you will have to Open the Storyboard again. This time choose “Interface Builder – Storyboard”.

The above steps will solve all the Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0 warnings.

Warning #2: Frame for “xxx” will be different at run time.
Description: This warning is letting you know that the frame for the object inside the storyboard does not match with the constraints that you connected on that object.

How to Resolve this issue?
Most of the time, this issue can be solved easily by going to the “Resolve Auto Layout Issue” tab and choose either “Update Frames” or “Update Constraints”.
Update Constraints

Sometimes, you may face a situation where the view controller has multiple Auto Layout Warnings. You may have already spend some time to fix the issue but the issue is too complicated that you might not be able to fix easily.

From my own experience in a situation like this, it is better to clear all the constraints for all the views inside the view controller. And then reconnect the constraints all over again for all the views. The chance is that after you reconnecting the constraints, you would not see the issue again.
Clear Constraints for all the views

More Auto Layout examples for iOS 7 and 8

On going…. Need some time to complete the tutorial under this section