Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

Flying Modals

With iOS 6 and Storyboards it is possible to create more advanced interactions which include your own navigational workflows which use your own view containers. With Flying Modals view controllers are embedded within an existing view controller at run-time by instantiating the view controller and attached view from the Storyboard and embedding it into the current view, allowing it to over the surface of the entire screen while being managed by a view controller dedicated to the model view.

Autolayout and constraints are now the norm and while they have been a challenge to learn they are becoming more useful all the time. Understanding Interface Builder within Xcode and Storyboards is half the effort. More on that later below...

Why Custom Modals?

We've worked in iOS with the Navigation Controller, Tab Bar Controller and the simple modal for a while now and it is just not enough anymore. We can make it more interesting. The Navigation Controller and Tab Bar Controller both containers for other view controllers which manage a set of view controllers and their related views. With iOS 5 there were new method in UIViewController for addChildViewController and removeFromParentViewController which allow third party developers to create our own containers which allow our view controllers to work with the same lifecycle that a view controller managed by a Navigation Controller would. This goes from loading and appearing to orientation changes. With the addChildViewController and removeFromParentViewController methods it is fairly easy to manage a container of your own view controllers and views. Managing a simple modal which is displayed and then dismissed is the easiest container and instead of presenting the usual modal which covers the existing view completely instead of allowing the modal to partially cover the current view to maintain the context of the current interaction so the user does not feel they are leaving the current view to do something else, which is not a good interaction for modals.

The new sharing Activities with UIActivitySheet are a good example of how modals could be for an app. The text entry UI appears above the keyboard which appears while the current view is still partially visible below.

Flying Modal 1

Flying Modal 1

The first flying modal covers the current view will a translucent mask before 2 boxes fly into the visible space from the left and right sides. The modal is dismissed with a button which is positioned at the bottom. The view which it covers is visible through this modal view. This sample is meant to show that the usual modal is not the only way to go. Sometimes a bit more interaction and movement can be done to make the workflow more interesting more function.

In this sample the blue box is on top while the red box is just below. It's possible that the red box could display controls for the modal while the top view shows a large text view or another sort of editor. The red box could also be moved out of view and replaced with another set of controls with a pan or swipe gesture.


Flying Modal 2

Flying Modal 2

The seconds modal also masks the current screen with a text view sliding down from the top. What makes this modal interesting is that automatically adapts for the 3.5" and 4" screens. This is done by using 2 constraints. The top constraint is used to first position the modal view out of view before animating it into the view. The other constraint is the height of the modal view which is set according to the height of the superview. Setting the height based on the superview the text view and other views within the modal view have constraints attached to the modal view so they are resized and repositioned accordingly. Managing these changes with the conventional frame position would take much more effort than simply adjustin the constant value of a couple of constraints.

Understanding Constraints in Storyboards

What makes constraints so difficult is that they are automatically generated by Interface Builder in Xcode and you cannot just delete them. It is hard to select a constraint on the design surface so it is necessary browse the Size Inspector for all of the constraints related to the current context on the design surface. The constraints which are purple cannot be deleted while the ones which are blue can be deleted, but often you want to eliminate a constraint which cannot be deleted. When you first work with autolayout and constraints not being able to simply manage constraints is frustrating. Learning how to make a purpe constraint turn blue is what will make your work much easier.

Typically if you have a view which has a constraint attached to the top and bottom it will adjust the height of that view as the superview changes height. This is the right behavior when that is intended but sometimes it is not. To delete one of these constraints you must set the height value so that either the top or bottom constraint can be deleted. You are not allowed to create an ambiguous layout with Interface Builder, which is why constraints which are purple cannot be deleted. You must first add a constraint which is redundant so that the constraint that you want to delete is not longer necessary to prevent an ambiguous layout. After you've had some practice with it a while you will start to get the hang of it.

For critical constraints which are used in code to move views with animations you will want to take steps to ensure these constraints are not accidentally lost when working in Interface Builder. To manipulate the constraint an IBOutlet is connected to the constraint and during viewDidLoad it helps to assert that the IBOutlet is defined so when a constraint is accidentally detached it will be noticed immediately. In the case of this project I defined a custom assertion in the precompiled header (.pch) called MAAssert which works best for my purposes. You may be find with simply using NSAssert. The main reason for using MAAssert is that the NSAssert macro references self which becomes a problem with ARC when using blocks which is common with Grand Central Dispatch which is used commonly.

License: BSD


Brennan Stehling
SmallSharpTools
@smallsharptools (App.net)
@smallsharptools (Twitter)