# Understand and Use Closures in Swift

Have you ever seen some factory method in UIKit and see this strange parameter called `completion` or `completionHandler`? Usually you put `nil` there and leave it alone. These strange things like `(Double,Double) -> Bool` things are closures. Closures are functions you use as types, often in parameters of other functions. In this lesson we’ll explore closures and get under the hood to explain what they are and what they are really doing.

# Set Up a Playground

Set up a playground in Xcode, the iPad or on the web at the IBM Swift Sandbox. IF using the IBM Swift Sandbox, make sure you have Foundation imported.

`import Foundation`

# The Basics of Closures

Suppose I want to calculate the volume of a deep dish pizza. Add these functions to the playground:

``` //area of a round pizza
}
//volume of a round pizza
func roundVolume(height:Double, radius:Double ) -> Double{
}
```

Add a variable to compute the volume of a pizza of radius 6 and height 2, then print it

```var volume = roundVolume(height:2,radius:6)
print( String(format:"Round volume %4.2f",volume))
```

Run this and get the volume from the area on the console. Which is fine if I had only round pizzas. What if I had rectangle, oval or triangle pizzas? I’d have to write two new functions each: one for the area and one for the volume. However in each case I’m only changing the area calculation. What if I could pass just the calculation to the volume function? That’s what a closure is: a way of writing something like a function but assigning it as a type. Add the function to the class.

```func volume(
height:Double,
dim1:Double,
dim2:Double,
area:(Double,Double) -> Double) -> Double
{
return area(dim1,dim2) * height
}
```

Look at the parameter `area`. I’ve declared it `(Double,Double) -> Double`. That looks a lot like a function that returns `Double`, and two `Double` parameters. That’s what a closure does as a type. A closure gives a skeletal structure like a function you can pass as a parameter. Below the `volume` function add the following line of code.

```let rectangleArea = { (length:Double,width:Double) -> Double in
return length * width
}
```

When I declare the contents of the identifier, I flesh out something like a function inside of curly braces. Instead of `func` before the parameters, I put `in` after the return type. There are parameters `(length:Double,width:Double)`. I have the return type as a `Double`. For closures, there must always be a return value. If you don’t have one mark it `Void` or `()`.

Since I declared the type in the closure declaration, I often can remove it from the declaration

```
let  rightTriangleArea = {(length,width) -> Double in
return length * width / 2.0
}
let ovalArea = {(length,width)->Double in
return length/2.0 * width/2.0 * M_PI
}```

It doesn’t work in all cases though. This give an error if you do not specify the type

```let roundSliceArea = { (radius:Double, slices:Double) ->Double in
}
```

I can use the same volume function and change how I compute the area.

```print (volume(height: 2,dim1: 10, dim2: 12, area:rectangleArea))
print (volume(height: 2,dim1: 10,dim2: 12, area:roundSliceArea))
print (volume(height: 2,dim1: 10, dim2: 12, area:rightTriangleArea))
print (volume(height: 2,dim1: 10, dim2: 12, area:ovalArea))
```

I do have a problem with a circle. I could define it like this in my storyboard:

``` let circleArea = {(radius)->Double in
}
print (self.volume(height: 2,dim1: 10, dim2: 12, area:circleArea))
```

This doesn’t work for the circle, because the number of parameters are different. You’d get this error message
`Cannot convert value of type '(Double) -> Double' to expected argument type '(Double, Double) -> Double'`

You have choices: Use the oval with the same length and width or a placemarker.  I tend to choose the place marker. Change `circleArea` to add the extra parameter. Fix the above code to this:

```let circleArea = {(radius:Double, placeMarker:Double) -> Double in
}
print (volume(height: 2,dim1: 10, dim2: 12, area:circleArea))
```

# Literal Closure in Parameters

You don’t have to assign the closure to a constant. You can write it explictly in the function. For a rectangle area, you can write this in the playground.

```
volume = volume(
height: 2,
dim1: 10,
dim2: 12,
area: {(width,length)->Double in
return width * length
}
)
print(volume)
```

You’ll find this a very common way of specifying the closure. When the closure is the trailing parameter, you can place it after the function like this:

```volume =  volume(
height: 2,
dim1: 10,
dim2: 12)
}
print(volume)
```

# Closures as Completion Handlers

One very common use of closures is completion handlers. Make a new function like this:

```func volume(
height:Double,
dim1:Double,
dim2:Double,
completionHandler:(Double)->()
){
let result = dim1 * dim2 * height
completionHandler(result)
}
```

Neither the `completionHandler` closure nor the `volume` function returns anything. Instead the result is the parameter of the completion handler.
Why would anyone do this? The reason is asynchronous processing. There are methods which Apple or the developer don’t want to run in the main thread. If you are querying a database, or opening a file any results appear in a closure. The database query might take some time, and you don’t want the rest of your application to freeze while you wait for the result. Similarly, while loading a file you don’t want to freeze the system waiting to learn if the load was successful.
Instead of `return` in these functions, the method runs on another thread at its own pace and lets the main thread go on its merry way. When done, the method calls something like `completionHandler`, `handler`, or `completion` with the results it returns as the completion parameter.

The developer uses the result their implementation of the completion handler. This is why most often closures happen completely within a function call. Usually they are specific to the code around it. For example, the `volume` function with the `completionHandler` would code like this to save the result to the volume property and output the result.

```volume(height: 2,dim1: 10,dim2: 12)
{(result)->() in
print(result)
volume = result  //in a class use self
resultLabel.text = String(format:"Completion %5.2f")
}
```

Completion handlers often pass off the value to a property in a class, like the code above assigns the value of  `result` to `volume`. If you run the code above within a class, be sure to include the class identifier or `self`. `volume = result` should be `self.volume = result`. The identifiers within a closure have no scope to the class. They must be explicitly stated.

# A Real Example of a Completion Handler

As a general rule, you’ll find completion handlers when you don’t know when you will complete a task. One good example of this is presenting alert views.

Set up a new single view project named ClosureDemo, with Swift as the language. Go to the storyboard and drag a label and button.

Set the font on both to Title 1.  Select the button. Title the button Alert. Click the alignment icon in the auto layout menu bar. Check Horizontally in Container and Vertically in container.  Change Update from to Items of new constraints like this:

Click Add 2 constraints.  Select the Label. Title it Results.  Click the pin icon  in the auto layout toolbar.  In the dialog box that appears type 10 then tab, 10 then tab and 10 then tab. Click down to the bottom and Update frames with Items of New Constraints.

Open the assistant editor and control-drag the label to the code. Name the outlet resultsLabel. Control-Drag from the button to the code. Change to an action. Name the action presentAlert.

Close the Assistant editor.  Open the `Viewcontroller.swift` code.

In the `presentAlert` action, add the following code:

``` @IBAction func presentAlert(_ sender: UIButton) {
volume = 240.0
//example of a real completion handler.
message: "Volume is \(volume)",
```

Alert actions only activate after the alert shows and the action’s button gets tapped by the user. The `UIAlertAction` initializer uses handlers to describe the action when pressed. Add this to the compute action:

```
title: "Clear", style: .destructive,
handler: {(action)->() in
self.volume = 0
self.resultLabel.text = "Cleared"
}
)
```

In `clearAction`, the user sets the `volume` property to 0 and reflects that in the Label.  Again, the closure is independent of the scope of its class. You must specify `self` in order to use the `ViewController` classes’ properties and methods.

Add two more examples of actions:

```
title: "Double",
style: .default,
handler: {(action)->() in
self.volume *= 2
self.resultLabel.text = "\(self.volume)"
})
title: "Cancel",
style: .cancel,
handler:{(action)->() in
self.resultLabel.text = "\(self.volume)"
})
```

```alert.addAction(clearAction)
```

Finally present the alert controller. `present` has a completion handler. Add a `print` statement to it to see it in action, then a `print` after the `present`.

```
{()->Void in
print ("present Completed")
})
print ("Outside Handler")
```

Build and run. Tap the Alert button. You get the alert. The console printed this:
``` Outside Handler present Completed ```
After calling `present`, The system executed the next step, and did not wait for it to finish printing  Outside Handler. Once the presentation completed, the system printed present Completed. The alert shows:

Tap the double button. The label reads 240. Try the other buttons.

You’ll find closures in most often in these handlers. Anything that takes and unpredictable amount of time will use a handler in a closure.

# The Whole Code

You can find the code for this tutorial on the IBM Swift Sandbox. For cutting and pasting into an Apple Playground on iPad or Xcode, Use the code below.

```//
// Closure Demo file
// For MakeAppPie.com  closure tutorial
// Sep 2016 by Steven Lipton
//
//
import Foundation

//area of a round pizza
}
//volume of a round pizza
func roundVolume(height:Double, radius:Double ) -> Double{
}
print( String(format:"Round volume %4.2f",volume))

//Closure to change the area formula
func volume(
height:Double,
dim1:Double,
dim2:Double,
area:(Double,Double) -> Double) -> Double
{
return area(dim1,dim2) * height
}

//Assigning type (Double,Double) -> Double to Classes

let rectangleArea = { (length:Double,width:Double) -> Double in
return length * width
}
let  rightTriangleArea = {(length,width) -> Double in
return length * width / 2.0
}
let ovalArea = {(length,width)->Double in
return length/2.0 * width/2.0 * M_PI
}
let roundSliceArea = { (radius:Double, slices:Double) ->Double in
}
//Trying out the volume function

print (volume(height: 2,dim1: 10, dim2: 12, area:rectangleArea))
print (volume(height: 2,dim1: 10,dim2: 12, area:roundSliceArea))
print (volume(height: 2,dim1: 10, dim2: 12, area:rightTriangleArea))
print (volume(height: 2,dim1: 10, dim2: 12, area:ovalArea))

//Fitting a single parameter formula with a placemarker
print (volume(height: 2,dim1: 10, dim2: 12, area:circleArea))
// closure within parameters
volume = volume(height: 2, dim1: 10, dim2: 12, area: {(width,length)->Double in return width * length})
print(volume)
// Trailing closure outside parentheses
volume =  volume(height: 2, dim1: 10, dim2: 12) {
}

//Closures as Completion Handlers
func volume(
height:Double,dim1:Double,dim2:Double,
completionHandler:(Double)->()
){
let result = dim1 * dim2 * height
completionHandler(result)
}

// For asynchronous processing, use the closure instead of returning the result.
volume(height: 2,dim1: 10,dim2: 12)
{(result)->() in
print(result)
volume = result

}

```

This is the code for the ClosureDemo Alert project. Add the label and button as described above than connect to this code in ViewController.

```//
//  ViewController.swift
//  ClosurePlay
//
//  Created by Steven Lipton on 9/9/16.
//

import UIKit

class ViewController: UIViewController {

var volume = 0.0

@IBOutlet weak var resultLabel: UILabel!
@IBAction func compute(_ sender: UIButton) {
volume = 240.0
//example of a real completion handler.
message: "Volume is \(volume)",

title: "Clear", style: .destructive,
handler: {(action)->() in
self.volume = 0
self.resultLabel.text = "\(self.volume)"
})

title: "Double",
style: .default,
handler: {(action)->() in
self.volume *= 2
self.resultLabel.text = "\(self.volume)"
})
title: "Cancel",
style: .cancel,
handler:{(action)->() in
self.resultLabel.text = "\(self.volume)"
})

present(alert, animated: true, completion: {()->Void in
print ("In present Handler")
})
print ("Outside Handler")

}

}

}
```

# Tab Bar Controllers in Xcode 8 Storyboards

In this lesson, we’ll take a look at tab bar controllers and how to add them in the storyboard.  For more on implementing them completely in code see Swift Swift: Using Tab Bar Controllers in Swift. For more on data sharing once set up in the storyboard, see Passing Data in Tab Bar controllers

# The Real Difference between Navigation and Tab Bar Controllers

Before we begin, It’s important to remember the difference between  tab bar and navigation controllers. Navigation controllers are stack based, while tab controllers are parallel in execution. Think of a navigation controller as a stack of cards. You can only play the visible card. If you put a card on top of another card, only the top card is active.

Now imagine you take several cards and deal them face up. You can play any face up card. They all are active. This is a tab bar controller.

As we go through lessons on tab bar controllers, it is very important to remember this difference.

# Creating From the Template

The easiest way to make a tab bar controller is through Xcode’s template. In Xcode, press Command-Shift-N or File>New>Project. Select the tabbed application.
This will give you a window with two tabs installed with two labels each and a tab item on the bottom of each controller. The template tends to make things more complicated instead of less, so it is rarely used.

# Creating From A Single View

The most common way to make a tab bar controller is to start from a single view and embed it in a controller. We’ll try an example of this one in Xcode. Press Command-Shift-N and select Single View. Make a file named SwiftTabBarEmbed, using Swift as the language and with a Universal device. Once created, go over to the Storyboard.  Make sure the Preview setting is  View as: iPhone6s(wC hR) in the lower left corner of the storyboard:

Change the color of the view controller’s background.

Select the view controller by clicking the view controller icon or title, and select Editor>Embed in>Tab Bar Controller.

This will turn the single view controller into the first view controller of the tab bar.

Add another view controller by dragging out a view controller then control-dragging from the tab bar controller to the new controller. In the pop-up, select under Relationship Segue the view controllers option.

Another segue appears on the story board.

You’ll see a second tab in the tab bar controller.

## Adding More Tabs with System Icons

To configure the tab bar icon, go to the Item icon in the  Yellow View Controller (not on the tab view controller) we just made and click it.

This will bring up in the properties inspector the Tab Bar Item and Bar Item properties. In the Tab Bar Item properties is the System Item drop down. This is where we configure the tab bar button.

In the System Item menu, Click the drop-down for System Item. you will see a  list of system icons.

Select Favorites. The Icon changes both on the view controller and the tab bar controller.

Click the other view controller’s tab bar, and change the system Icon to Recents.

# Using  the More Feature

Click on the Preview size Button which reads iPhone 6s(wC hR). A new toolbar appears underneath it. Select the iPad 9.7″.

The view controllers in the storyboard change to iPads, so you may need to change the zoom level.

Drag out  six more view controllers, so we have a total of eight controllers.  Change their background colors to make then easily distinguishable.

Control-drag from the tab bar controller to each new view controller and assign ContactsBookmarksSearch, Downloads, and Most Viewed to the controllers, leaving one more as a custom item. The tab bar controller should look like this:

Change the Preview mode back to to an iPhone 6s. While your icons may be in a  different order, you will get something like this for the tab bar at the bottom of the phone:

Compact widths, the width on most phones, cannot handle more than five tabs. If you add more than five tabs, it places a More tab as the fifth tab. What does the More tab do? Build and run as an iPhone 6s in the simulator.

Tap on the More icon in the lower right. A table appears with the missing tabs.

Tabs selected by More act slightly differently than ones in a regular tab. They are embedded in a navigation controller. You’ll see at the top a navigation bar.

The navigation bar goes back to the More table.  Tap Bookmarks, and notice the navigation bar is not there, then tap More again and the Downloads controller is still there.

Select More  in the navigation bar to go back to the Table view

## User Editing the Tab Bar with More

Without any extra code, tab bar controllers let users customize their tab bars. Tap the Edit button, and you get a configuration view:

Looking closer, you’ll see that the hidden tabs are highlighted and the visible tabs are dimmed

Drag the Item tab down to the tab bar. Drop it on top  of Recents. It replaces Recents.

You can also drag tabs in the tab bar to change the order. Drag Downloads on top of Contacts. Drag  Downloads to the right, swapping it with Bookmarks.  Your tab bar now looks like this:

I want to add two cautions to this: One of the system icons you can use is a More icon. Be careful when using the More icon in a tab bar. It can cause user confusion between the More tab and your own use for More. Make sure it is clear what you are doing.

The second caution is more insidious. When programming for tab controllers, you can get the tabs from an array. However, the order and visible tabs can change by user request with  the More tab. Avoid hardwiring the tabs by their location in the array since users can change them.

Close the simulator. In the storyboard, delete the Bookmarks, Recents and Favorites view controllers (or their segues if you don’t mind the warnings)  so you get a tab bar like this:

As we now have five icons, this will keep off the More icon, which requires six tabs to show up. You can reorder the tabs in the tab view controller by drag and drop.   Reorder using drag and drop to this:

# Custom Tab Bar Items

Click on the tab bar for the Item view  controller. We can see all the tab bar properties.

The lower half has bar item properties, which directly control the title and icon for the tab. We can easily change the text. Change the Bar Item Title to Pie.

The title changes on the tab bar:

If we change a System items’s title, it becomes a custom item, and the icon disappears. Do the same to change Downloads to Pizza. Also change Contact to Square.  SquarePizza and Pie have squares for icons.

## Icon Images

Under Title in the properties inspector,  we have a drop down for Image.

For a custom bar item we can supply the icon. Image icons are not like other images. They are monochrome images,  unlike anything else you have ever seen. They are set not by color but by the alpha value , or transparency of the image. You can make any image here any color, but it will show up as a solid tint color if you select an alpha value of 100% and background color if you select 0% alpha. For example I created the following icons in both high and low resolutions:

Icons are 30 points by 30 points, which means for retina images make the icon a 60 pixel by 60 pixel image and for low resolution images 30 pixel by 30 pixel. You can download them individually by right clicking the images above, and saving them to a folder.  Use these file names:

For those not familiar with Apple image naming conventions, low resolution images have a file name. Retina Images have @2x appended to that file name. This tells Xcode to know what resolution it is. We have both 60×60 pixel retina and 30×30 pixel standard images. By loading both into Xcode, the system will use the correct one automatically for the device.
In Xcode’s navigator panel, open up Assets.xcassets. Select all the icon files. Drag them into the center panel in Xcode, which will highlight. Release the mouse button, and you will see a new collection in the image assets.

Return to the storyboard. On the tab we titled Square,click anywhere on the tab bar.  Select the image drop-down in the tab bar properties and select the gradient bar icon.

The Gradient bar now replaces the place marker  square:

Find the Pizza and Pie tab views on the storyboard, and change them the same way. The Tab bar controller now has three custom icons.

Build and run with the iPhone 6 simulator, and you will see our three icons, with  Pie  highlighted as selected.

# Using View Controllers in Tab Bar Controllers

As mentioned earlier, tab bar controllers make a set of single view controllers running parallel to each other. The tab bar switches the view, but the view we leave does not get dismissed, just hidden. there are two uses for such a controller. The first is a series of small independent applications related to each other. Apple’s clock app is an exmaple. The timer, alarm clock, world clock, and stopwatch all are related by a theme of time. All run independently of each other. The second use of Tab bar controllers is to use a shrared data set in different ways. Social media apps like Twitter or Instagram for example use tab bars to have different functions of displaying posts, searches, or displaying notifications that all use the same database. For this second type of use, see see Passing Data in Tab Bar controllers. We’ll look at the first type here.

## Basic View Controllers

Connecting a view controller in tab bars is the same as hooking up any other view controller. Make a new view controller class by pressing Command-N. Make a new Cocoa Touch Class view controller named SearchViewController. Change the class code to this.

```class SearchViewController: UIViewController {
var count = 0
@IBOutlet weak var myLabel: UILabel!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
myLabel.text = "Count \(count)"
count += 1
}
count = 1
}
}
```

Note how I used `viewDidLoad` and `viewWillAppear` here. In tab bar controllers, `ViewDidLoad` only fires once, when we first load the view controller. Use it for first initializations only. The code above initializes the count to 1. The method `viewWillAppear` fires every time the view appears, and so we use that to do any updating. This code assumes that this view controller will remain active even when it is not visible.

Go to the storyboard and select the Search view controller on your storyboard. In the identity inspector set the class to SearchViewController.

On the search view controller  in the storyboard drag a label to the center of the view.

Set the label font size to 32 points. Click the auto layout align button   at the bottom right of the storyboard. In the menu that appears, check Horizontally in Container and Vertically in Container  with values of 0 points. Set Update Frame to Items of New Constraints.

Add the two constraints. Open up the assistant editor. Drag from the circle next to the outlet to the label to connect it.

Build and run. Select the search tab, then another tab a few times. You will see the count increase every time you return to the search tab.

## Embedding Navigation Controllers in Tab Bar Controllers

You can also embed navigation controllers into tab controllers. Stop the simulator and go back to the storyboard. Close the Assistant editor if it is open. Select the Pizza View Controller’s icon on the storyboard. In the drop down menu, select Editor>Embed in>Navigation Controller

The view controller changes into a Navigation controller with the tab bar icon. Attached to the navigation controller is a view controller.

On the view controller, Double click the center of the navigation controller bar. Change the title to Pizza!!!. Drag a bar button item to the upper left of the controller on the storyboard. Title it More Pizza.

Add another view controller, next to  the one we just configured. Control-Drag from the bar button item to the new view controller. Set up a show segue. In the new view controller, Drag a Navigation item to the navigation bar. Change the item’s title to More Pizza!!!

Build and run. Select the Pizza tab and we have our navigation controller. Tap the More Pizza Button. The More Pizza!!! View Appears. Now go to another tab and then back to the Pizza tab. We remain on the More Pizza!!! view.

You can use navigation controllers inside a tab bar controller to your heart’s content. However, tab bar controllers can only be used once in a project, as the top level controller. Embedding more tab bar controllers does not work.

This is the basics of tab bar controllers. For more information on sharing between the controllers and a more extensive coding example, see Passing Data in Tab Bar controllers.

# How to Use MapKit for 2D and 3D Map Views.

Everyone may remember when Apple first introduced MapKit to replace Google Maps on iPhones, they ended up to apologizing. However over time, developers have found how easy it is to use MapKit. This API provides features which make using  both 2D and 3D maps very easy. More importantly, Google charges for map views  over a few thousand views and Apple doesn’t. For many applications requiring a lot of map views or when you have over a few thousand  users,  MapKit might make better sense for a developer not willing to pay the costs for an external API.

In this lesson, we’ll introduce MapKit, and how display a map in both 2d and 3d. We’ll discuss many of the attribute you have in the UIMapView class to make a great map. We’ll also talk about a small cheat using Google maps if you need only a few map points. Along the way I’ll throw in some Chicago history trivia.

# Make a New Project

Start by making a New Single-view  project Called MyMapKitDemo. Use a Universal device and Swift as the language.   When it loads, we need to turn on MapKit.  In the Project Properties, click on the the Capabilities tab.

You will see a list of functions we can use. About halfway down the list you’ll See Maps

Turn on maps and the menu opens.

We won’t be changing anything here, but the framework will load when we need it.

Go to the storyboard.  In the Object Library, find the  Map  Kit View object

Drag it somewhere on the story board.

Select the Map view. Click the   button in the Auto Layout  menu on the lower right of the storyboard. This will bring up the the pin menu. Click off Constrain to margins. Set the margins to be 0 on all sides. Change the Update Frames to Items of New Constraints.  Your pin menu should look like this.

Click Add 4 Constraints. The map view takes the entire view on the story board.

With the map view still selected, look at the attribute inspector.  At the top is some attributes specific to map views:

The Type attribute sets the map to be either  Standard, Satellite or Hybrid, which is combination of the two (a satellite with street names).  The Allows attributes control if the user can use zooming,scrolling rotation or 3D view. By default, the 3D view is on, and we’ll see this is a good thing.  The Shows attributes control extra items on the map. You’ll note User Location is off.  User location shows a dot where the user is. However that dot only shows up if the map shows a region the user happens to be in. Unless you live in the Lincoln Park or Chinatown neighborhoods of Chicago, in our app you won’t be visible.

We’ll be changing a few of these through properties in code. You can leave them alone for now.

Add  seven buttons to the view.  Select all seven buttons.  In the attributes inspector, find the Text color button, and click the color swatch in the button.

A color palette appears. Using the RGB colors, change the color to a Dark Blue (#000088) color.

In the attributes inspector,  scroll down to View.  Click the swatch for the background color. Change the Background to White  #FFFFFF and set the Opacity to 50%

Change the title on the seven buttons to CPOGWrigley, Connie’s, Satellite, 2dMapFlyOver,  and Clean Map. Arrange everything like this.

Select the CPOG,Wrigley and Connie’s buttons.  Click the Stack view Button in the auto layout buttons. In the attributes inspector, change the stack view to a Horizontal Axis, Alignment of Fill, Distribution of Fill Equally and Spacing of 0:

Click the pin button .  Turn off Constrain to Margins. Set the top constraint to 20 points and the left and right to 0 points, leaving the bottom  unchecked. Set Update Frames to Items of New Constraints.

Select the Satellite, 2D Map, Flyover, and Clean Map buttons.  Click the Stack view Button in the auto layout buttons. In the attributes inspector, change the stack view to a Horizontal Axis, Alignment of Fill, Distribution of Fill Equally and Spacing of 0. Click the pin button .  Turn off Constrain to Margins. Set the bottom constraint to 20 points and the left and right to 0 points, leaving the top  unchecked. Update Frames to Items of New Constraints.

Add the three constraints. The final layout looks like this:

We need to wire up the outlets and actions. Go to the ViewController.swift file.  Before we do anything else, MapKit is a separate framework than UIKit.  Just under the `import` `UIKit` add `import` `MapKit`

```import UIKit
import MapKit
```

Once you do that, change the `viewController` class to add all of our outlets and actions:

```class ViewController: UIViewController {
//MARK: Properties and Outlets

@IBOutlet weak var mapView: MKMapView!

//MARK: - Actions

//MARK: Location actions
@IBAction func gotoCPOG(sender: UIButton) {
}
@IBAction func gotoWrigley(sender: UIButton) {
}
@IBAction func gotoConnies(sender: UIButton) {
}

//MARK: Appearance actions
@IBAction func toggleMapType(sender: UIButton) {
}
}
@IBAction func flyoverMap(sender: UIButton) {
}
@IBAction func toggleMapFeatures(sender: UIButton) {
}

//MARK: Instance methods

//MARK: Life Cycle
}
}
```

Go back to the storyboard, and open the assistant editor in Automatic. Drag from the circle next to `gotoCPOG` to the CPOG button on the storyboard. Do the same from `gotoWrigley` to Wrigley, `gotoConnies` to Connie’s, `toggleMapType` to Satellite, `overheadMap` to 2D Map, `flyoverMap` to FlyOver, and `toggleMapFeatures` to Clean Map. Finally, drag from the outlet `mapView` to the mapView.

Build and run. You get a map of the continent you happen to be in.

This is the default setting of a map view – a region that takes in a continent closest to the current location according to the simulator. Since all the attributes were left on, you can pan and zoom on this map.  To zoom on a simulator, hold down the Option key and drag with the mouse.  I zoomed in on Chicago, where we’ll be in the app.

# Getting Sample Location Data From Google Maps

We’ll need some sample location data. I’m going to pick  my favorite baseball field and two favorite pizza restaurants to for this.  MapKit uses several coordinate systems, but the most important is  latitude and longitude. If you need only a few points to test it’s easy to get them by looking up the location in Google Maps. Maps has the location information embedded in the URL for the view.

Go to the web and in Google maps, search for Wrigley Field. If you want the address to search, it’s the one Elwood Blues uses in the Blues Brothers: 1060 W. Addison.

Or you can just go to https://www.google.com/maps/place/Wrigley+Field. When it appears, Click your mouse in the middle of the intersection of Addison and Clark Streets.

If you look at the URL you find something similar to this

`https://www.google.com/maps/place/Wrigley+Field/@41.9472901,-87.6565357,21z/data=!4m2!3m1!1s0x880fd3b2e59adf21:0x1cea3ee176ddd646`

The important part is from the /@ to the next Slash.

`/@41.9472901,-87.6565357,21z`

That’s the map coordinates in latitude and longitude of that intersection. For Apple maps we need one other piece of data: what direction we are pointing, known as the heading. To get that, drop the little guy for Street Siew onto the same intersection, pointing towards the big red Wrigley Field sign.  You get this data

`@41.9471939,-87.6565108,3a,75y,41.73h,90.81t/`

The first two are the map coordinates again. They may not match exactly our first pair.  the important number for us is the heading `41.73h` which tells us the compass direction we are pointing, 41.73 degrees from north.

The three pieces of data we need are latitude 41.9471939 longitude -87.6565108, and heading 41.73 degrees. You can use this method to get coordinates if you have no other way to get the data. In upcoming lessons, we’ll take coordinate data directly from City of Chicago databases and remove this step.

# Core Location Data Types

We represent data for maps in the Core Location data types. Here’s a table to summarize:

CL Type Type Description/Notes
CLDegrees Double A latitude or Longitude
CLDirection Double A heading in degrees based on the distance from North 0 degrees
CLDistance Double A Distance in meters
CLSpeed Double A speed in meters/Second
CLLocationCoordinate2D struct {
var latitude: CLLocationDegrees,
var longitude: CLLocationDegrees,}
A coordinate on a map based on latitude and longitude
CLAccuracy Double The accuracy of a coordinate value in meters.

We’ll use most of these as we build our app. We’d like some way of storing the data we collected from Google Maps in some constants. I made a struct to do that. Add this to `ViewController`.

```//MARK: Location constants
struct cameraInfo{
var location = CLLocationCoordinate2D()
init(
latitude:CLLocationDegrees,
longitude:CLLocationDegrees,
){
self.location = CLLocationCoordinate2D(
latitude: latitude,
longitude: longitude)
}
}
```

We store a `CLLocationCoordinate2D` and a `CLLocationDirection`. To make `location`, we use two `CLLocationDegrees`, one for latitude and one for longitude.

We can use this to save our Wrigley data. Add this to `ViewController` under the struct.

```let wrigleyLocation = cameraInfo(
latitude: 41.9471939,
longitude: -87.6565108,
```

To save you from looking up the two pizza restaurants, I’ll add them for you. Add this  to your code under the `wrigleyLocation`.

```let CPOGLocation = cameraInfo(
latitude: 41.920744,
longitude: -87.637542,
let conniesLocation = cameraInfo(
latitude: 41.849294,
longitude: -87.6414665,
```

# Setting the Map Region

The next step in writing a map app is to set a region. Regions define the visible area based on a center point and a diameter in latitude and longitude. If we were in the real world you think of it as the circle you could visibly see. Since device screens are rectangular, they create a kind of rectangle and set scaling for the map like this.

I said sort of because this is not planar geometry, it’s the spherical geometry of the planet. This region has a type of `MKCoordinateRegion` There is an intializer to get this region, but it uses the differences in map coordinates to define the region. The easier one to use for our purposes is the function `MKCoordinateRegionMakeWithDistance` which takes the three parameters in the illustration above.
We’ll use this function to get the region defined by a radius from the circle, then assign it to our map. Add this to the code as an instance method:

```//MARK: Instance methods
func setRegionForLocation(
location:CLLocationCoordinate2D,
animated:Bool)
{
let span = 2.0 * spanRadius
let region = MKCoordinateRegionMakeWithDistance(location, span, span)
mapView.setRegion(region, animated: animated)
}
```

We set the region in our map view with the `setRegion` method. Since it can be animated we included a parameter in our function to animate the region change. Add this to `viewDidload`:

```setRegionForLocation(
wrigleyLocation.location,
animated: false)
```

When we start our application, we’ll start the application with a radius of 150 meters. Build and run.

There’s the stadium in the upper right. While most people know about the Chicago Cubs, they don’t know about the other team that used to play there, founded by a guy who missed the boat.  In 1915 this guy ran late and  missed the boat for his company picnic. The boat, the Eastland capsized in the Chicago River at the Clark Street bridge killing 855 people.

Five years later, this guy would co-found   American football’s professional league the  NFL. George Halas’  team started playing in Wrigley field in 1922, deriving  their name- The Chicago Bears  – from the baseball team.

# Using Cameras

Besides Papa Bear Halas’ origin story,  what you might not know is this is a 3d map.  You are just looking at it from overhead. In MapKit we use cameras to look at 3d maps. It allows us to change the angle and perspective we are looking at the object.  Change the `flyoverMap` action to this:

```@IBAction func flyoverMap(sender: UIButton) {
let camera = MKMapCamera()
camera.centerCoordinate = mapView.centerCoordinate
camera.pitch = 80.0
camera.altitude = 100.0
mapView.setCamera(camera, animated: true)

```

The `camera` property of MapKit is the view we see of the map. It has four properties, which we set all of them in this method. The `centercoordinate` is a coordinate the camera centers its view. `pitch` is the angle up or down of the camera. `altitude` is how high in the air is the camera. `heading` is the compass direction the camera faces. We set this camera 80 degrees from vertical, 100 meters in the air with a heading northeast. Build and run. Tap the Flyover button and you get the following in the simulator.

If you run on a phone instead of a simulator, you get a more robust image, with 3d buildings.

While you can set all three camera properties on your own, you can also use a few methods as well. Change the `gotoCPOG` action to this:

```@IBAction func gotoCPOG(sender: UIButton) {
let camera = MKMapCamera(
lookingAtCenterCoordinate: CPOGLocation.location,
fromDistance: 0.01,
pitch: 90,
mapView.setCamera(camera, animated: true)
}
```

Here we use the initializer `MKMapCamera:lookingAtCenterCoordinate:fromDistance:pitch:heading:` method. We use the `CPOGLocation.heading` to get the heading.   This method just takes all our properties and makes a camera that is 1 centimeter from the location, pitching the camera at the horizon, and setting the heading according to our constant . This should be close to a human’s eye view.

This location is in front of Chicago Pizza and Oven Grinder, the inventors of the bowl pizza. Ingredients are placed in a ceramic bowl and the crust is placed over the top of the bowl. The bowl is baked and then inverted, making a pizza. There’s something else about this location, but build and run first. Click The CPOG button. On the simulator you get this:

On a phone, you’ll find the iPhone is more robust with graphics  than the simulator.:

First one more bit of Chicago history. You’ll notice a inset from the buildings I marked with a red arrow.

There’s a gap between the buildings that’s now a parking lot. There was a garage there once. This was the site of the infamous St. Valentines Day Massacre.  The blue arrow is Pizza and Oven Grinder at 2121 N. Clark, and legend has it Jack McGurn, Al Capone’s lieutenant rented a room on the second floor a few weeks before the massacre to scope out the garage.

Okay enough history. You’re probably noticing the big software problem. We should be getting a human’s eye view pf the street. Instead we get a pigeon.  This is one of the problems with Apple Maps in 3D: there is a minimum altitude that’s about 30 meters. Apple didn’t call it flyover for nothing. On a phone if you two-finger drag up, and you notice the display does not want to pitch any more.

## 2D Views Revisited

If the code gets a value that makes no sense from a 3Dview, it places a 2D view instead.  We can see this with  another way of positioning the camera. This method takes a center coordinate, a coordinate for the camera and an altitude. It finds the pitch by doing math to the eye coordinate and altitude.  Add this code

```@IBAction func gotoWrigley(sender: UIButton) {
let camera = MKMapCamera(
lookingAtCenterCoordinate: wrigleyLocation.location,
fromEyeCoordinate: wrigleyLocation.location,
eyeAltitude: 200)
mapView.setCamera(camera, animated: true)
}
```

This code uses the same two coordinates for the location.  With the same two coordinates, MapKit makes the camera into a overhead camera. Build and run, then press the Wrigley button

All we’ve done is zoom in on our Wrigley coordinates.  Change the action to this:

```@IBAction func gotoWrigley(sender: UIButton) {
var eyeCoordinate = wrigleyLocation.location
eyeCoordinate.latitude += 0.005
eyeCoordinate.longitude += 0.005
let camera = MKMapCamera(
lookingAtCenterCoordinate: wrigleyLocation.location,
fromEyeCoordinate: eyeCoordinate,
eyeAltitude: 50)
mapView.setCamera(camera, animated: true)
}
```

We increased our eye coordinate to be 0.005 degrees north and 0.005 degrees west of the center coordinate. Build and run. When we tap the Wrigley button now, we get this in the simulator:

We’ve moved around to the northeast  corner of the ballpark. Using this method, the heading will always be  looking at the  center coordinate, in this case  Clark and Addison.

Another way to show a 2Dmap by camera is set the `pitch` to 0. Add this code:

```@IBAction func gotoConnies(sender: UIButton) {
let camera = MKMapCamera(
lookingAtCenterCoordinate: conniesLocation.location,
fromDistance: 1300, pitch: 0,
mapView.setCamera(camera, animated: true)
}
```

When you  build, run and try the Connie’s button, you get this:

Connie’s Pizza marks mile 21 of the Chicago Marathon, one of the flattest courses  and oddly the highest average elevation (590m) of the six major league marathons. If you want to set world records for running 26.2 miles or get that Boston Qualifier, this is the race to do it, and many do.

You can of course set the map view’s camera directly. Add this code to show a 2D map of any point,  at an attitude of 1000 meters.

```@IBAction func overheadMap(sender: UIButton) {
mapView.camera.pitch = 0.0
mapView.camera.altitude = 1000.0
}
```

Build and run. First show CPOG as a 3D map, then click the 2D Map button.

Clark is a diagonal street heading northwest out of Chicago. It may be a good idea to set `heading` to 0 and show north as up. Change the code to this

```@IBAction func overheadMap(sender: UIButton) {
mapView.camera.pitch = 0.0
mapView.camera.altitude = 1000.0
}
```

Now you get something that makes more sense as a static map on a phone:

# Using Satellite Imagery

In MapKit there are three types of maps: Standard, Satellite and Hybrid.  Standard is the default type we’ve been using already. Satellite gives satellite imagery, but no road information. Hybrid combines the road information of standard with the satellite image.

We control the map type with the `maptype` property.  Add this to the `gotoConnies` action.

`mapView.mapType = .Satellite`

Now run the app, and tap the Connie‘s button. you get a satellite overhead map.

Change `.Satellite` to `.Hybrid` and you get this

You can easily see both the pizza icon for my favorite pizza in Chicago and the  south branch of the Chicago river in this photo.  The south branch of the Chicago river is part of one of the marvels of modern engineering: it flows backwards from its natural course.  The river flow project, completed in 1900, reverses the river flow so sewage flows down to the Mississippi River  entering not far from St. Louis  instead of into Chicago’s water supply of Lake Michigan. Just In case you are worried, Chicago now cleans their water before they do that today.

## Satellite and Flyover

That’s however is not the whole story. To use flyover 3d on a satellite or hybrid map there are two more types: `.SatelliteFlyover` and `.HybridFlyover`.  Change  `gotoWrigley`, to this

```@IBAction func gotoWrigley(sender: UIButton) {
var eyeCoordinate = wrigleyLocation.location
eyeCoordinate.latitude += 0.004
eyeCoordinate.longitude += 0.004
let camera = MKMapCamera(
lookingAtCenterCoordinate: wrigleyLocation.location,
fromEyeCoordinate: eyeCoordinate,
eyeAltitude: 50)
mapView.mapType = .HybridFlyover
mapView.setCamera(camera, animated: true)
}```

I moved in the coordinates a bit more to get a better look at the ballpark. Build and run. Tap the Wrigley button. You get this on a phone:

So you can experiment with the different types and what they will do, let’s add some code to toggle the type. Change the `toggleMapType` to this

```@IBAction func toggleMapType(sender: UIButton) {
let title = sender.titleLabel?.text
switch title!{
case "Satellite":
mapView.mapType = .Satellite
sender.setTitle("Hybrid", forState: .Normal)
case "Hybrid":
mapView.mapType = .Hybrid
sender.setTitle("Standard", forState: .Normal)
case "Standard":
mapView.mapType = .Standard
sender.setTitle("Satellite", forState: .Normal)
default:
mapView.mapType = .Standard
sender.setTitle("Satellite", forState: .Normal)
}
}
```

We use a `switch` statement from the `titleLabel.text` of the button to toggle between the types. These are the 2d types for `.Satellite` and `.Hybrid`. We need a little code to to use the 3d types when we turn on flyover.  Change the `flyoverMap` action to this.

```@IBAction func flyoverMap(sender: UIButton) {
//change to the correct type for flyover
switch mapView.mapType{
case .Satellite:
mapView.mapType = .SatelliteFlyover
case .Hybrid:
mapView.mapType = .HybridFlyover
case .Standard:
mapView.mapType = .Standard
default:
break
}

let camera = MKMapCamera()
camera.centerCoordinate = mapView.centerCoordinate
camera.pitch = 80.0
camera.altitude = 100.0
mapView.setCamera(camera, animated: true)
}
```

Build and run. Try a few combinations of the buttons. Here’s a one minute video if you don’t have a phone handy.

The time to render some of these images is rather long. There’s a lot of processing and data transmission. Each location changes the region dramatically, so everything has to load over again. The rendering time is short only for the `.Standard` flyover version. Keep this in mind as you are using these types.

# Toggling features

While `.Satellite` tuns off all the features like attractions, rendering buildings and the like, there are a few properties you can use in the `.Standard` mode to control these. Change `toggleMapFeatures` to this

```    @IBAction func toggleMapFeatures(sender: UIButton) {
let flag = !mapView.showsBuildings
mapView.showsBuildings = flag
mapView.showsScale = flag
mapView.showsCompass = flag
mapView.showsTraffic = flag
}

```

Play with this a little.  Go to Connie’s Pizza and set to `.Standard` Mode. Tap Clean Map. Everything but road names disappears.

Tap Busy Map.  We get back our attractions, plus the scale and traffic.

You’ll notice the compass doesn’t show. When the `.heading` is 0. there is no compass. If the user rotates the map, then the compass will show.

Tap Flyover and we get the 3d view with buildings

Tap Clean Map and we get just the roads and river.

Play around with these. You may find some of the combinations don’t work. Some of the `mapType`s set and use these features in specific ways. Check the  MKMapView Class Reference for more information.

You can display a lot of information through a map view. We’ve seen that coding a map in 2d or 3d is not that difficult as long as you have some coordinate data. We’ve also seen that Apple provides a lot of attractions such as restaurants and sports stadiums for you. We have not yet added our own locations and features, known as annotations and overlays. In our next lesson, we’ll take a 2d map and annotate it with some data.

# The Whole Code

```//
//  ViewController.swift
//  MyMapKitDemo
//
//  Created by Steven Lipton on 5/4/16.
//

import UIKit
import MapKit

class ViewController: UIViewController {
//MARK: Location constants
struct cameraInfo{
var location = CLLocationCoordinate2D()
self.location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
}

let wrigleyLocation = cameraInfo(latitude: 41.9471939, longitude: -87.6565108, heading: 41.73)
let CPOGLocation = cameraInfo(latitude: 41.920744, longitude: -87.637542, heading: 338.0)
let conniesLocation = cameraInfo(latitude: 41.849294, longitude: -87.6414665, heading: 32.12)
//MARK: Properties and Outlets
@IBOutlet weak var mapView: MKMapView!
//MARK: - Actions

//MARK: Location actions

@IBAction func gotoCPOG(sender: UIButton) {
mapView.setCamera(camera, animated: true)
}

@IBAction func gotoWrigley(sender: UIButton) {
var eyeCoordinate = wrigleyLocation.location
eyeCoordinate.latitude += 0.004
eyeCoordinate.longitude += 0.004
let camera = MKMapCamera(lookingAtCenterCoordinate: wrigleyLocation.location, fromEyeCoordinate: eyeCoordinate, eyeAltitude: 50)
mapView.mapType = .HybridFlyover
mapView.setCamera(camera, animated: true)
}

@IBAction func gotoConnies(sender: UIButton) {
let camera = MKMapCamera(lookingAtCenterCoordinate: conniesLocation.location, fromDistance: 1300, pitch: 0, heading: 0.0)
mapView.mapType = .Hybrid
mapView.setCamera(camera, animated: true)
}

//MARK: Appearance actions

@IBAction func toggleMapType(sender: UIButton) {
let title = sender.titleLabel?.text
switch title!{
case "Satellite":
mapView.mapType = .Satellite
sender.setTitle("Hybrid", forState: .Normal)
case "Hybrid":
mapView.mapType = .Hybrid
sender.setTitle("Standard", forState: .Normal)
case "Standard":
mapView.mapType = .Standard
sender.setTitle("Satellite", forState: .Normal)
default:
mapView.mapType = .Standard
sender.setTitle("Sat Fly", forState: .Normal)
}
}

mapView.camera.pitch = 0.0
mapView.camera.altitude = 1000.0
}

@IBAction func flyoverMap(sender: UIButton) {
switch mapView.mapType{
case .Satellite:
mapView.mapType = .SatelliteFlyover
case .Hybrid:
mapView.mapType = .HybridFlyover
case .Standard:
mapView.mapType = .Standard
break
default:
break

}

let camera = MKMapCamera()
camera.centerCoordinate = mapView.centerCoordinate
camera.pitch = 80.0
camera.altitude = 100.0
mapView.setCamera(camera, animated: true)
}

@IBAction func toggleMapFeatures(sender: UIButton) {
let flag = !mapView.showsBuildings
mapView.showsBuildings = flag
mapView.showsScale = flag
mapView.showsCompass = flag
mapView.showsTraffic = flag
mapView.showsPointsOfInterest = flag
if flag {
sender.setTitle("Clean Map", forState: .Normal)
} else {
sender.setTitle("Busy Map", forState: .Normal)
}
}

//MARK: Instance methods
let span = 2.0 * spanRadius
let region = MKCoordinateRegionMakeWithDistance(location, span, span)
mapView.setRegion(region, animated: animated)
}

//MARK: Life Cycle
}
}

```

# The Step by Step Guide to Custom Presentation Controllers

Ever wanted that sliding sidebar or an alert with a image picker? Apple has many great ways of presenting view controllers,  but sometimes we want something different, something new. For that we subclass `UIPresentationController`. However there’s a few concepts that you’ll need to wrap your head around first. In this lesson we’ll create a few standard controllers to explain the custom controllers, then make and animate our own custom controller sliding  side bar. We’ll build the presentation controller step by step, so you know how it really works.

# Custom Presentation Anatomy in Alert Views.

Make a new project called SwiftCustomPresentation, with a universal device and Swift as the language.  Once loaded go to the launchscreen.storyboard. I like to have some indication that things are working, and since Apple removed the default launch screen layout, I tend to add my own. Set the background color to Yellow(#FFFF00). Drag a label on the launch screen  and title it Hello in 26 point size.  Click the alignment auto layout button at the bottom of the storyboard and check on Horizontally in Container and Vertically in Container set to 0. Update the frames for  Items  of  new constraints, then click Add 2 constraints.

You now have a nice label in the center of the launch screen

Go to the storyboard. Make the background Yellow(#FFFF00). Drag a button to the center of the storyboard. Title the label Hello, Pizza as a 26 point size system font. Make the text color Dark Blue(#0000AA) Just like the label on the launch screen, align the button to the center of the storyboard.  Click the alignment auto layout button at the bottom of the storyboard and check on Horizontally in Container and Vertically in Container set to 0. Update the frames for  Items  of  new constraints, then click Add 2 constraints.

Open the assistant editor. Control drag from the button to the code. Create an action entitled `showAlert`. Close the assistant editor for now. Ooen the ViewController.swift file.  Change the action to this:

```@IBAction func showAlert(sender: UIButton){
}
```

```func helloAlert(){
title: "Hello Slice",
title: "Okay",
style: .Default,
handler: nil)
animated: true,
completion: nil)
}
```

This is  code to present the simplest alert possible.  We create a simple alert and give it one action, an Okay button that dismisses the alert. The last line is the important one for our discussion:

```
animated: true,
completion: nil)
```

As of iOS8, all modal view controllers present with this one method.  You tell the method which controller you want to present, set a few properties on it and it does the work, no matter what your device. It relieves a lot of the hard work of developers specifying exceptions for individual devices.

Set your simulator for an iPhone 6s. Build and run.  When the Hello pizza button shows in the simulator, tap it. You get your alert.

We’ve made this alert to illustrate the three parts you need to know about any custom view controller.

Our yellow background is the presenting view controller, the controller that calls the `presentViewController `method The alert, which is the presented view controller, is the controller `presentViewController` uses in its parameters.

`presentingViewController.presentViewController(presentedViewController, animated:true,completion:nil)`

In an alert and in other view controllers such as popovers, the `presentViewController` method adds a special view  between the presented and presenting view controllers called a chrome. The chrome is the difference or padding between the bounds of the presented controller, and the bounds of the presenting controller. Usually it is a solid color with some alpha value. Apple tends to use a gray color for chrome, which is why yellow is looking like a dark orange yellow.

Alerts help us explain the anatomy of a presentation controller. However they are rather automatic in their execution. Let’s add a simple modal view controller to play with custom view controllers.  Press Command-N and select a new Cocoa Touch Class ModalViewController. Do check on Also Create XIB file. This is one of those places I prefer xibs due to portability over the storyboard.

Save the file. Go to  the ModalViewController.xib file. Change the background to Dark Blue(#0000AA). Add two labels to the xib. In one make the text Ready for your slice? , a Font of 26.0 Bold, and White(#FFFFFF) text. Set the Alignment to Left justified. Set the  Lines  property to 0 and the Line Breaks  to Word Wrap. This will let the label vary the number of lines to fit the text, and word wrap the results. Your attributes should look like this:

For the second label, add a short paragraph. I used a passage from Episode 4 of my podcast A Slice of App Pie.

This is the other thing about persistence: It does not see success as an absolute. It is not a Bool, a true/false variable, but a Double,  a real number. It is not just black or white, but every color.  You are not a success, but you are at a degree of success. Your past experience fuels your future success.

Set the  Font to 16.0 Regular, and White(#FFFFFF) text. Set the Alignment to Full  Justified. Set the  Lines  property to 0 and the Line Breaks  to Word Wrap.

Select the text paragraph and Control drag  down and to the right until you are over the blue of the background.

Release the mouse button and you will see an auto layout menu. Hold down shift and Select  Trailing Space to Container, Bottom Space to Container and Equal Widths:

Click the Add Constraints button. Now control-drag from the Ready label to the paragraph label.  In the auto layout menu that appears, Shift-Select Vertical Spacing, Trailing, and Equal Widths

Click the Add Constraints button. Select the paragraph and go to  the size inspector .  You’ll see a list of constraints:

Your values will most likely be different than the illustration. Click the edit button for the Trailing Space to: Superview. A popup appears. Change the Constant to 8.

Click the Equal Width: to Superview edit button. Change the Multiplier to 0.9.

Edit the Bottom Space to: Superview constraint. Change the Constant to 20.

Edit the Align Trailing Space to: Ready for yo… constraint. Change the Constant to 0.

Edit the Top Space to: Ready for yo… constraint. Change the Constant to 20.

Edit the Equal Width to: Ready for yo… constraint. Change the Multiplier to 0.5.

If you’ve never worked with auto Layout before, what we just did is anchor the bottom right corner of the paragraph to the bottom right corner of the xib. with a margin of 20 points on the bottom and 8 points on the right. We set the width of the paragraph to 90% of the width of the xib. The Label above it, acting as a title, we made half as long as the paragraph, and aligned to the right side of the paragraph, 20 points up.

Click  the triangle tie fighter which is the auto layout  resolve button. You get a menu like this:

Select for the All Views in View section Update Frames. You now have a layout like this:

We’ll dismiss this modal with a swipe to the right. In the object library,  find the swipe gesture:

Drag it to the blue of the xib and release. Nothing will happen there but in the document outline (if you don’t have it open click the  button)  you will see a new object listed

Select the Swipe Gesture Recognizer and in the attributes menu, you should see the following:

These are the defaults and what we want: a single finger swipe to the right.  Open the assistant editor and control-drag the Swipe Gesture Recognizer from the document outline to the code. Create an action named dismissModal.

In the code that appears, dismiss the vew controller:

```@IBAction func dismissModal(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}```

## Presenting the View Controller.

Go back to the ViewController.swift File.  Add the following method:

``` func presentModal() {
let helloVC = ModalViewController(
nibName: "ModalViewController",
bundle: nil)
helloVC.modalTransitionStyle = .CoverVertical
presentViewController(helloVC,
animated: true,
completion: nil)
}```

The code gets the view controller  and the xib then presents it. We’re using the default settings for a modal in this case.

Go to the storyboard.  Open the assistant editor if not already open. Drag a Swipe Gesture recognizer to the storyboard. Select it in the the document outline and change the Swipe attribute  to Up. Control-drag from the Swipe Gesture recognizer and make an outlet

```@IBAction func swipeUp(
sender: UISwipeGestureRecognizer) {
presentModal()
}
```

Build and run.You should be able to swipe up and show the blue controller.

The title is too small to fit on one line and adapts to two. Rotate the phone (in the simulator press Command right-arrow) and you get a slightly different layout:

Swipe right and the view dismisses

# Custom Presentation #1: A  Big Alert View

We’ve got a working modal view controller. We did this for several reasons. This proves there’s no magic in what we are about to do. It also reinforces how we do this in a standard presentation controller.

## Adding the Custom Presentation Controller

Create a new class by pressing Command-N on the key board in Xcode. Make a new cocoa touch class MyCustomPresentationController subclassing `UIPresentationController`.  You end up with an empty class:

```class MyCustomPresentationController: UIPresentationController {
}```

```let chrome = UIView()
let chromeColor = UIColor(
red:0.0,
green:0.0,
blue:0.8,
alpha: 0.4)```

A presentation controller needs to do three things: Start the presentation, end the presentation and size the presentation. The `UIPresentationController` class has three methods we override to do this: `presentationTransitionWillBegin`, `dismissalTransitionWillBegin` and `frameOfPresentedViewInContainerView`. There is a fourth method `containerViewWillLayoutSubviews` which may sound familiar to those who have worked with code and auto layout. When there is a change to the layout, usually rotation, this last method will make sure we resize everything.

First we present the controller. In our code we control what the chrome does. To our custom presentation controller, add the following method

```override func presentationTransitionWillBegin() {
chrome.frame = containerView!.bounds
chrome.alpha = 1.0
chrome.backgroundColor = chromeColor
containerView!.insertSubview(chrome, atIndex: 0)
}```

First we set the size of the chrome by the size of `containerView`. The `containerView` property is a view which is an ancestor of the presenting view in the view hierarchy. `containerView` gives us a view that is bigger to or the same size as the presenting view. Setting the chrome to this size means the chrome will cover everything. We then set the color and alpha of `chrome`, and then add `chrome` to the container view.

Our next method to implement is `dismissalTransitionWillBegin.` We’ll remove the chrome from the view hierarchy here. Add this code:

``` override func dismissalTransitionWillBegin() {
self.chrome.removeFromSuperview()
}
```

We’ll change the size of the presented view so we can see the chrome. Size changes take two methods. The first is `frameOfPresentedViewInContainerView`. Add the following code:

```override func frameOfPresentedViewInContainerView() -> CGRect {
return containerView!.bounds.insetBy(dx: 30, dy: 30)
}```

This returns the frame of the container. We used the `insetBy` function to shrink it 30 points within the container view. This will give us a effect similar to an alert.

To make sure adaptive layout changes everything, we need one more method. add this:

```override func containerViewWillLayoutSubviews() {
chrome.frame = containerView!.bounds
presentedView()!.frame = frameOfPresentedViewInContainerView()
}
```

Our first line changes the chrome’s size to fit the new size of the view. The second one makes sure that the presented view is the correct size by calling the method we just wrote `frameOfPresentedViewInContainerView`.

Custom presentation controllers run through a delegate. Above the `MyCustomPresentationController` class, add the following:

```class MyTransitioningDelegate : NSObject, UIViewControllerTransitioningDelegate {
func presentationControllerForPresentedViewController(
presented: UIViewController,
presentingViewController presenting: UIViewController,
sourceViewController source: UIViewController
) -> UIPresentationController? {
return MyCustomPresentationController(
presentedViewController: presented,
presentingViewController: presenting)
}
}```

This is a subclass of the `UIViewControllerTransitioningDelegate`. Though the parameters are long, the single function in the delegate returns our presentation controller, using the designated initializer for the class.

That is all we need for a bare bones custom controller. Our next step is to use it.

## Using the Custom Presentation Controller

We’ll add a left swipe gesture for presentation this controller. Go to the storyboard. Drag a swipe gesture control on the view. Set the Swipe attribute this time for Left. Open the assistant editor and control-drag this gesture to the `ViewController` class, making a new action swipeLeft. Change the new function to this:

```@IBAction func swipeLeft(sender: UISwipeGestureRecognizer) {
presentCustomModal()
}```

Close the assistant editor and go to the ViewController.swift code. Add the following to the `ViewController` class, under to the `presentModal` function so you can compare the two

```func presentCustomModal(){
let helloVC = ModalViewController(
nibName: "ModalViewController",
bundle: nil)
helloVC.transitioningDelegate = myTransitioningDelegate
helloVC.modalPresentationStyle = .Custom
helloVC.modalTransitionStyle = .CrossDissolve
presentViewController(helloVC,
animated: true,
completion: nil)
}```

Like the standard modal controller, we get the controller and present it. We did change the transition style to tell the difference between the two controllers, and as you’ll see a cross dissolve makes a better transition for this type of view.

Unlike `presentModal`, we set the `modalPresentationStyle` to `.Custom` so `presentViewController` knows to look for a custom presentation controller. However it won’t work without setting the view controller’s `transitioningDelegate` property. The transitioning delegate tells the view controller where the custom transition is. If this is `nil`, the presentation is a standard presentation, not a custom one.

We haven’t set the delegate yet. At the top of the `ViewController` class, add this line:

`let  myTransitioningDelegate = MyTransitioningDelegate()`

Build and Run. Once Hello,Pizza appears, swipe left and the modal view appears with chrome around it.

Rotate the device .

Swipe right and the view disappears

# Why Apple Uses Gray Chrome

You’ll notice that the chrome does not turn blue, but instead tuns green. As a transparent color, it blends with the color under it, sometimes not in the most attractive way. This is why Apple uses gray for chrome — you never have the problem with gray. If we change the chrome’s `backgroundColor` like this:

```//let chromeColor = UIColor(red:0.0,green:0.0,blue:0.8,alpha: 0.4) //mixes with background colors
let chromeColor = UIColor(white: 0.5, alpha: 0.6) //gray dims the background
```

Then build and run. We get a  slightly different effect:

You’ll notice in both these cases however, the presented controller seems to glow. This is not because of code, but a trick of your brain called Simultaneous contrast . The brain has a hard time dealing with two hues that are complements next to each other, so it starts to make things up to compensate. I used two colors most likely to do this to each other, blue and yellow. There are two strategy you can use to prevent this. One is use less jarring colors in your color scheme for your app. The second is to change the chrome to have a high alpha value and not be as transparent. Change the code to this:

```//let chromeColor = UIColor(red:0.0,green:0.0,blue:0.8,alpha: 0.4) //mixes with background colors
//let chromeColor = UIColor(white: 0.4, alpha: 0.6) //gray dims the background
let chromeColor = UIColor(red:0.0,green:0.0,blue:0.8,alpha: 0.7) // not as transparent```

The chrome is very blue, and the effect is far less.

Set the chrome back to the gray for the rest of the tutorial.

# Animating the Chrome

You’ll notice that the chrome appears and disappears rather abruptly. We need to add some animation to the chrome so it transitions smoothly. There is  an object called a transition coordinator that automatically loads into the view controller during presentation. It gives you a way to do animation parallel to the main animation.  There’s a method in the transition coordinator `animateAlongTransition:completion:` that we’ll use to fade the chrome as the presented controller fades in.

In the `MyCustomPresentationController` class, change the method to this

```override func presentationTransitionWillBegin() {
chrome.frame = containerView!.bounds
//chrome.alpha = 1.0
chrome.backgroundColor = chromeColor
containerView!.insertSubview(chrome, atIndex: 0)
presentedViewController.transitionCoordinator()!.animateAlongsideTransition(
{context in
self.chrome.alpha = 1.0
},
completion: nil)
}```

We changed to code to start the chrome with an `alpha` of 0. The `transitionCoordinator` function returns the transition coordinator as an optional value. We use its `animateAlongsideTransition` method to transition for the invisible chrome to a visible one.

In the `presentationTransitionWillBegin`, we do nothing in the completion closure of `animateAlongsideTransition`. On the other hand, we’ll remove the chrome in the `dismissalTransitionWillBegin`. Add this code.

```override func dismissalTransitionWillBegin() {
presentedViewController.transitionCoordinator()!.animateAlongsideTransition(
{ context in
self.chrome.alpha = 0.0
},
completion: {context in
self.chrome.removeFromSuperview()
}
)
//self.chrome.alpha = 0.0
//self.chrome.removeFromSuperview()
}```

We fade out the chrome, and once the chrome completely fades at the end of the main animation, we remove the view.

With those changes, build and run. The chrome fades in and out smoothly

# Custom Presentation #2: A Sidebar

A comma use for a custom presentation controller is a toolbar or side bar. Let’s modify the code to make a sidebar on the right side of our device.

## Changing the frame

For a side bar we are setting the view on one side of the `contentView` instead of the center as we do with `insetBy`. Change `frameOfPresentedViewInContainerView` to

```override func frameOfPresentedViewInContainerView() -> CGRect {
//return containerView!.bounds.insetBy(dx: 30, dy: 30)  //center the presented view
let newBounds = containerView!.bounds
let newWidth:CGFloat = newBounds.width / 3.0 // 1/3 width of view for bar
let newXOrigin = newBounds.width - newWidth //set the origin from the right side
return CGRect(x: newXOrigin, y: newBounds.origin.y, width: newWidth, height: newBounds.height)
}
```

We commented out the `insetBy`, and took control of the frame directly. We take the size of the container view, and divide by three to make a frame size  a third the width of the container. We also set the origin to one-third less the width of the container view to make the bar on the right. Build and run. It’s there, but portrait does not look so good.

Landscape looks a lot better, since it has more space

We can change the proportions to fit better. We’ll make it 3/4 of the width. Change the code to this:

`var newWidth:CGFloat = newBounds.width * 0.75 // 3/4 width of view for bar`

This will work, but will be way too big on an iPad or iPhone 6 plus in landscape. We can use a trait collection to reduce the size to one third on the bigger devices. add this to the code, just under the `newWidth` declaration:

```if containerView!.traitCollection.horizontalSizeClass == .Regular{
newWidth = newBounds.width / 3.0 //1/3 view on regular width
}```

Change your simulator to an iPhone 6s plus. Build and run. In  portrait, we get a 3/4 view

In landscape, with the regular width size class, we get a  1/3.

Change to an iPad Air 2 simulator. We get 1/3 on both landscape and portrait.

# Animating the Side Bar

Side bars look best when they transition by sliding in. While we can animate the chrome with `animateAlonsideTransition`, we cannot do so for the frame of the presented controller. To do that we need to use another class,  `UIViewControllerAnimatedTransitioning`.

While making a new class is probably a better way of doing this, I’m going to keep it  together with the presentation controller.  Just under  the `import UIKit` in `MyCustomPresentationController.swift,` add the following:

```class MyAnimationController: NSObject,UIViewControllerAnimatedTransitioning{
var isPresenting :Bool
let duration :NSTimeInterval = 0.5
}
```

The  `UIViewControllerAnimatedTransitioning`  protocol contains a series of functions to create an animation for both dismissal and presentation.  It has two required functions, where we use these two properties.

We added two properties to our class. `isPresenting` will be our indicator if this is a dismissal or presentation. To make it easier to use, add this to the class:

```init(isPresenting: Bool) {
self.isPresenting = isPresenting
super.init()
}```

This will set the value when we initialize the class. We’ll use it in a required method `animateTransition`. This method tells the system what to do when there is a transition. We’ll set it up to do both a presentation animation and a dismissal. Add this code:

```func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
if isPresenting {
animatePresentationTransition(transitionContext)
} else {
animateDismissalTransition(transitionContext)
}
}```

The parameter `transitionContext` type `UIViewControllerContextTransitioning` contains all the information you need to do the animation transition, including the presented and presenting controllers and the container view. We’ll pass those on to two more functions we’ll write shortly to animate presentation and dismissal of the presenting view controller.

Our other property, `duration` will set the time for the animation duration in the other required function. Add this code:

``` func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return duration
}
```

This satisfies the two required functions for the protocol. We are still getting errors for out two animation functions though. Add these to the class:

```func animatePresentationTransition(transitionContext: UIViewControllerContextTransitioning){
}
func animateDismissalTransition(transitionContext: UIViewControllerContextTransitioning){
}```

Our first step is to add a presentation animation in `animatePresentationTransition`. We animate using one of the UIView animation class methods `animateWithDuration`. There are different version for different effects, whihc you can read more about in the UIView Class Refrence. All of these will use closures to describe the end state of the animation. We set the presenting view controller to a state where we will star the animation, then in the animation block give its final state. The `animateWithDuration` does the rest.

To present the controller’s animation, we’ll need a few thing from the the transition context. Add this to the code for `animatePresentationTransition`

```        // Get everything you need
let presentingViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let finalFrameForVC = transitionContext.finalFrameForViewController(presentingViewController)
let containerView = transitionContext.containerView()
let bounds = UIScreen.mainScreen().bounds
```

We get the `presetingviewController` to be able to set its state before and after animation. We also get the container view for adding the presenting view controller. The `finalFrameForVC` is the `CGFrame` that will be the end of the animation. We’ll use bounds to give us the bounds of the visible screen.

The next step is to change the frame of the presenting view controller to where it should be before the animation begins. we want it off to the right side of the visible view. Since we are not moving anything in the Y direction, we want to have our starting point as the width of the visible view. Add this code:

```        //move our presenting controller to the correct place, and add it to the view
presentingViewController.view.frame = CGRectOffset(finalFrameForVC, bounds.size.width, 0)
presentingViewController.view.alpha = 0.0
```

Besides the presenting view moving off of stage right, I also dimmed the view to an `alpha` of 0.0. I then added the view to the container view. The next step is the big one — add the animation with this code:

```//animate the transition
UIView.animateWithDuration(
transitionDuration(transitionContext), //set above
delay: 0.0,
options: .CurveEaseOut, //Animation options
animations: { //code for animation in closure
presentingViewController.view.frame = finalFrameForVC
presentingViewController.view.alpha = 1.0
},
completion: { finished in  //completion handler closure
transitionContext.completeTransition(true)
}
)```

There’s a lot of unpack in this method’s parameters. We start with a duration we get from the `transitionDuration` method we defined earlier. Next thre is a delay to begin the animation, which we leave at ). The next parameter `options` takes a value from `UIViewAnimationOptions` to describe the behavior of the animation.

The next parameter, animations, describes the final state of the animation. In our code it sets the view controller’s frame to the final frame fro the presentation, and sets the `alpha` to 1.

Once the animation is complete there is a completion handler, where we set in the transition context a flag that says we are done animating.

For a dismissal, we do the same in reverse.Add this to `animateDismissalTransition`:

```
let presentedControllerView = transitionContext.viewForKey(UITransitionContextFromViewKey)
let containerView = transitionContext.containerView()
```

We first get our presented controller view and the container view. This time, the current position of the frame is the position we start from, so there is no setting the initial frame of the animation. Instead we got straight into the animation, which animates the presented controller view to the edge of the container view. Add the animation:

```        // Animate the presented view off the side
UIView.animateWithDuration(
transitionDuration(transitionContext),
delay: 0.0,
options: .CurveEaseIn,
animations: {
presentedControllerView!.frame.origin.x += containerView!.frame.width
presentedControllerView!.alpha = 0.0
},
completion: {(completed: Bool) -> Void in
transitionContext.completeTransition(completed)
}
)
```

## Add the Animations to the Delegate

The `UIViewControllerTransitioningDelegate` does more than just hold the custom transition controller. It has optional methods for animation. Add to `MyTransitioningDelegate` the following

```func animationControllerForPresentedController(
presented: UIViewController,
presentingController presenting: UIViewController,
sourceController source: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return MyAnimationController(isPresenting:true)
}
```

After a long list of parameters, we return a `MyAnimationController` with `isPresenting` set to true. We set to false for a dismissal in this function

```func animationControllerForDismissedController(
dismissed: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return MyAnimationController(isPresenting:false)
}
```

Build and run. We now have an animated custom transition

# More Things to Try.

This rather long tutorial just breaks the ice in what you can do with a custom presentation. You do not have to use a xib, for example, Storyboards works just as well, with either segues or storyboard id’s plus a reference to the delegate. There are many more animation options as well.

Also a word of caution. I intentionally used a lot of optional values as explicit values to keep things simple and readable. You might not want to be as careless as I am here, and check for `nil` or optional chain much more often than I did in this code.

# The Whole Code

## ViewController.swift

```//
//  ViewController.swift
//  SwiftCustomPresentation
//
//  Created by Steven Lipton on 4/7/16.
//

import UIKit

class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
let  myTransitioningDelegate = MyTransitioningDelegate()

//MARK: Actions
}
@IBAction func swipeLeft(sender: UISwipeGestureRecognizer) {
presentCustomModal()
}

@IBAction func swipeUp(sender: UISwipeGestureRecognizer) {
presentModal()
}
//MARK: Instance methods
title: "Hello Slice",
title: "Okay",
style: .Default,
handler: nil)
animated: true,
completion: nil)
}

func presentModal() {
let helloVC = ModalViewController(nibName: "ModalViewController", bundle: nil)
helloVC.modalTransitionStyle = .CoverVertical
presentViewController(helloVC, animated: true, completion: nil)
}

func presentCustomModal(){
let helloVC = ModalViewController(nibName: "ModalViewController", bundle: nil)
helloVC.transitioningDelegate = myTransitioningDelegate
helloVC.modalPresentationStyle = .Custom
helloVC.modalTransitionStyle = .CrossDissolve
presentViewController(helloVC, animated: true, completion: nil)
}

//MARK: Life Cycle
}

// Dispose of any resources that can be recreated.
}

}

```

## MyCustomPresentationController.swift

```//
//  MyCustomPresentationController.swift
//  SwiftCustomPresentation
//
//  Created by Steven Lipton on 4/7/16.
//

import UIKit

class MyAnimationController: NSObject,UIViewControllerAnimatedTransitioning{

var isPresenting :Bool
let duration :NSTimeInterval = 0.75

init(isPresenting: Bool) {
self.isPresenting = isPresenting
super.init()
}

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return duration
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
if isPresenting {
animatePresentationTransition(transitionContext)
} else {
animateDismissalTransition(transitionContext)
}
}

func animatePresentationTransition(transitionContext: UIViewControllerContextTransitioning){
// Get everything you need
let presentingViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let finalFrameForVC = transitionContext.finalFrameForViewController(presentingViewController)
let containerView = transitionContext.containerView()
let bounds = UIScreen.mainScreen().bounds

//move our presenting controller to the correct place, and add it to the view
presentingViewController.view.frame = CGRectOffset(finalFrameForVC, bounds.size.width, 0)
presentingViewController.view.alpha = 0.0

//animate the transition
UIView.animateWithDuration(
transitionDuration(transitionContext), //set above
delay: 0.0,
options: .CurveEaseOut, //Animation options
animations: { //code for animation in closure
presentingViewController.view.frame = finalFrameForVC
presentingViewController.view.alpha = 1.0
},
completion: { finished in  //completion handler closure
transitionContext.completeTransition(true)
}
)
}

func animateDismissalTransition(transitionContext: UIViewControllerContextTransitioning){

let presentedControllerView = transitionContext.viewForKey(UITransitionContextFromViewKey)
let containerView = transitionContext.containerView()

// Animate the presented view off the side
UIView.animateWithDuration(
transitionDuration(transitionContext),
delay: 0.0,
options: .CurveEaseInOut,
animations: {
presentedControllerView!.frame.origin.x += containerView!.frame.width
presentedControllerView!.alpha = 0.0
},
completion: {(completed: Bool) -> Void in
transitionContext.completeTransition(completed)
}
)
}
}

class MyTransitioningDelegate : NSObject, UIViewControllerTransitioningDelegate {
func presentationControllerForPresentedViewController(
presented: UIViewController,
presentingViewController presenting: UIViewController,
sourceViewController source: UIViewController
) -> UIPresentationController? {
return MyCustomPresentationController(
presentedViewController: presented,
presentingViewController: presenting)
}
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return MyAnimationController(isPresenting:true)
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return MyAnimationController(isPresenting:false)
}
}

class MyCustomPresentationController: UIPresentationController {
let chrome = UIView()
//let chromeColor = UIColor(red:0.0,green:0.0,blue:0.8,alpha: 0.4) //mixes with background colors
let chromeColor = UIColor(white: 0.4, alpha: 0.6) //gray dims the background
//let chromeColor = UIColor(red:0.0,green:0.0,blue:0.8,alpha: 0.7) // not as transparent

override func presentationTransitionWillBegin() {
chrome.frame = containerView!.bounds
chrome.alpha = 0.0
//chrome.alpha = 1.0
chrome.backgroundColor = chromeColor
containerView!.insertSubview(chrome, atIndex: 0)
var newframe = frameOfPresentedViewInContainerView()
newframe.origin.x = newframe.width
presentedViewController.view.frame = newframe
presentedViewController.transitionCoordinator()!.animateAlongsideTransition(
{ context in
self.chrome.alpha = 1.0
self.presentedViewController.view.frame = self.frameOfPresentedViewInContainerView()
},
completion: nil)
}

override func dismissalTransitionWillBegin() {
presentedViewController.transitionCoordinator()!.animateAlongsideTransition(
{ context in

self.chrome.alpha = 0.0
},
completion: {context in
self.chrome.removeFromSuperview()
}
)
//self.chrome.alpha = 0.0
//self.chrome.removeFromSuperview()
}

override func frameOfPresentedViewInContainerView() -> CGRect {
//return containerView!.bounds.insetBy(dx: 30, dy: 30)
let newBounds = containerView!.bounds
var newWidth:CGFloat = newBounds.width * 0.75 // 3/4 width of view for bar
//var newWidth:CGFloat = newBounds.width / 3.0 // 1/3 width of view for bar
if containerView!.traitCollection.horizontalSizeClass == .Regular{
newWidth = newBounds.width / 3.0 //1/3 view on regular width
}
let newXOrigin = newBounds.width - newWidth //set the origin 1/3 from the right side
return CGRect(x: newXOrigin, y: newBounds.origin.y, width: newWidth, height: newBounds.height)
}

/*
if containerView!.traitCollection.horizontalSizeClass == .Regular {
newWidth = newBounds.width * 0.33
} else { //compact and unknown 80%
newWidth = newBounds.width * 0.8
}
*/
override func containerViewWillLayoutSubviews() {
chrome.frame = containerView!.bounds
presentedView()!.frame = frameOfPresentedViewInContainerView()
}
}
```

## ModalViewController.swift

```//
//  ModalViewController.swift
//  SwiftCustomPresentation
//
//  Created by Steven Lipton on 4/7/16.
//

import UIKit

class ModalViewController: UIViewController {

@IBAction func dismissModal(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}

}
```

# Using Settings Bundles with Swift

Have you ever wondered how to put  user defined settings for your app into the settings app?  Xcode can create a special property list called a settings bundle which can append the  `NSUserDefaults` with more entries from Settings App.  You’ll find out in this lesson how to set up a settings bundle in your app for using the Settings App using XML. In the next lesson we’ll dive deep into the settings bundle using the property list editor.

I’ll assume you know how to use property lists and `NSUserDefaults` in this lesson. If you are not familiar with them you might want to check out my recent posts on Property Lists and `NSUserDefaults`

# Create the  Settings Bundle

Start a new Single view application  project in Xcode called SettingsBundleDemo using Swift and a Universal device.

Right-click on the SettingsBundleDemo group folder and select New file. Select the  Resources  category in the template window. Select Settings Bundle and click Next.

You should have name of settings. Keep the setting bundle in the SettingsBundleDemo Group  in the save window. Click Create.

The system will open up the settings bundle. which looks like a building block. In the Navigator open up the settings bundle by clicking on the arrow.

Click on the Root.plist file. You’ll see a property list  like this:

If closed, Open the Preference Items array. This is populated with demo data. Unlike other property lists,  this one does not directly store the value as a dictionary of values, but an array of dictionaries of controls. You pick the control you want in the Settings app by listing it in the property list. When we attach the settings bundle to the standard defaults of `NSUserDefaults`, the system will create key values in the `NSUserDefaults`.

The following table lists the type of controls that you can use:

Each type of control has several attributes.   If not already open, Open the Group Control, the Item 0 entry,  in Root.plist.

Groups are control used to group other controls together. They have only a title and a Type. Open the Item 3 (Slider).

The slider has more required controls, the ones listed here.  Many controls will have a  poorly named attribute Default Value. This is the value shown in  the settings app, not a true value of the default. It will show the values after the first use, but it is for display purposes not value purposes.

Each control type has its own attributes, as described in the chart above.  Here’s a list of all the possible attributes for the property list.

Delete the current entries. Property lists do not delete well in Root.plist.  The simplest way is to cut them out. Select Item 0 (Group). Right click on group, and select Cut in the menu. Then do the same for the Item 3( Slider)  and the rest of the controls. You should have a clean property list like this.

Select Preference Items.  Make sure it is open. The arrow should be pointing down.  Press the Add (+) button on the entry. A new entry appears.

There will also be a menu that opens. If you happen to click somewhere and lose the menu, click the down chevron()  in the entry. You get a list of controls.

Select Toggle Switch. This will give us a `Bool` value.  Open up the toggle switch control and you have the following attributes:

Click the value for each blank attribute, and set Title to  Room for cream.  Set Identifier to coffee_cream.  The identifier is the key for the `NSUserDefaults` entry.  Set the Default Value to YES. Your attributes should look like this:

Close the attributes for the switch, and select Item 0. Right click and select Add Row from the menu. Although it is the default, in the type menu, select Text Field.   Open up the Item 1(Text Field – ) to see the attributes.

Set the Title to Beverage of choice.  Set the Identifier to coffee_type. Right click on Identifier and select Add Row. A new row appears asking for an appropriate attribute:

Select the default Default Value. Set the Default Value to Coffee.

Close the attributes for the Text menu. Select the  Preference items entry, right click  and select Add Row.  The new row pushed the other rows down becoming Item 0. Select Multi-Value. Multi-value uses two arrays to make a selection table. Open up the attributes of the multi-value.  Set the title to Size. Set the Default Value to 0. Set the Identifier to coffee_size.

This control does not by default set up values. You must do that. Select the bottom attribute,  Right-click the entry, then choose Add Row.  Make the row type Values. Open Values‘ array, which should be empty. Using either the Add row or the + Icon, add four  sub rows to Values. Add the  number  0  to the first  row. Change the type of the row to Number.  Do the same for the other rows, making the values 1,  2 and 3.

Close the Values array. Add another attribute to the multi-value control Titles. Open the attribute’s array and add four entries. These will be  the strings Small, Medium, Large, and Extra Large.

We can look at our settings page now.  Just to make it easy to know when we can look at it, set the back ground in the Launchscreen.storyboard to Orange(#ff8000), and the Main.Storyboard to Yellow(#FFFF00). Build and run. When the Background turns yellow, go to the settings app.  If on a live device, hit the Home button. If on the simulator,  hit Command-Shift-H on your keyboard for the home button. Navigate to the settings app.

Scroll down to the bottom of the app. You’ll find our app there.

Click the item and we get a settings page.

# Setting up the Storyboard

Stop the app, then go to  Main.storyboard in Xcode. Add a switch, a label, a text field  and  a segmented control to the storyboard. Configure the controls to look like this:

Select the switch. In the size inspector, set Compression Resistance and Content Hugging to 1000 horizontally and vertically. Switches should never change size, and this prevents that from happening.

Click the stack view button to make a horizontal stack view. Select everything on the storyboard, and make vertical stack view by pressing the stack view button again.  Set the Stack View’s attributes to this:

Pin the stack view 71 up, 5 left and 5 right. Update frames for items of new constraints.

Open up the assistant editor and connect up the following outlets to their proper controls:

```@IBOutlet weak var roomForCream: UISwitch!
@IBOutlet weak var drinkText: UITextField!
@IBOutlet weak var sizeSegment: UISegmentedControl!
```

The `NSUserDefaults` does not know we have a settings bundle. Our first task is to register the settings bundle with `NSUserDefaults.`

```func registerSettingsBundle(){
let appDefaults = [String:AnyObject]()
NSUserDefaults.standardUserDefaults().registerDefaults(appDefaults)
}
```

This registers the settings bundle to the `NSUserDefaults` standard defaults. the `registerDefaults` method looks for property lists in the resources directory and changes the `value:key` entries to dictionaries of the form `[String:AnyObject]`. We only run this once in our code.

Make a new function updateDisplayFromDefaults and get our defaults

```func updateDisplayFromDefaults(){
//Get the defaults
let defaults = NSUserDefaults.standardUserDefaults()
}
```

Read the `key:value` pairs and assign them to our outlets. Add this to the function:

```//Set the controls to the default values.
roomForCream.on = defaults.boolForKey("coffee_cream")
if let drink = defaults.stringForKey("coffee_type"){
drinkText.text = drink
} else{
drinkText.text = ""
}
sizeSegment.selectedSegmentIndex = defaults.integerForKey("coffee_size")
```

The `stringForKey` method returns a optional value. Our code checks for a nil value and reacts accordingly. Add the new function to `viewDidload`:

```override func viewDidLoad() {
registerSettingsBundle()
updateDisplayFromDefaults()
}
```

We want to start fresh when we load the app. Go to the simulator or your device. Delete the application by pressing and holding on the app until it shakes. Once shaking, click the X to delete it. You will be asked

Click Delete and the app and the settings are now deleted. Build and run the application. We start with a blank preferences, since they haven’t been written to the app yet. Since the Default Value of the property list is a display value, it does not reflect here.

Press Command-Shift-H, then navigate over to the settings. Set your settings to this:

Press Command-Shift-HH to and select the demo app. Our app hasn’t changed.

Close the app in Xcode. Re-run the app. Now we get our defaults.

# Updating Defaults with Observers

Updating our preferences on restart only  is not a good thing. The problem is we need to tell the app that there was a change. This needs to be done automatically.In both a settings bundle and for `NSUserDefaults` within an app, this will be a frequent problem. You change a setting and want everywhere that uses it to update. Such changes need notification observers. I think of fire watchers as an analogy to observers. You have a forest ranger sitting in a tower looking for fire in the forest below. If she finds one, then she sets off an alrm to fight the fire to everyone in the forest. An observer does the the same thing in code. It looks for a certain event to happen, then runs a target method if is sees it happening. These events can be system defined events known as notifications (not to be confused with push notifications that show up on your device) or you can make up your own. I’ll discuss how to make notifications in a future post. We’ll concentrate on system generated ones.

The `NSUserDefaults` class generates a notification `NSUserDefaultsDidChangeNotification`. We can set an observer for the notification, and then run some code to update the display. Change `viewDidLoad` to this:

```override func viewDidLoad() {
registerSettingsBundle()
updateDisplayFromDefaults()

selector: "defaultsChanged",
object: nil)
}
```

We call the default notification center which keeps track of our observers to register it. This center is `NSNotificationCenter.defaultCenter()`. We add the observer with name `NSUserDefaultsDidChangeNotification` and tell it to run the function `defaultsChanged` when it observes a notification.

As an aside, you might be tempted to add the code from `registerSettingsBundle` as part of your `updateDisplayFromDefaults`. Every execution of `registerSettingsBundle` changes the `NSUserDefaults` by adding more defaults. Each time we add a default we get a notification, causing a recursive death spiral until we run out of memory. Keep it separate.

We’ll need a small function `defaultsChanged` to run when we have a notification. Add this to your code:

```func defaultsChanged(){
updateDisplayFromDefaults()
}
```

There’s also a bit of legacy code we have to add. Prior to iOS9, we need to remove the observer for good memory management. In iOS9 and later, ARC does that for us. For any iOS8 devices, add the following to remove the observer.

```deinit { //Not needed for iOS9 and above. ARC deals with the observer.
}
```

The code uses the Swift class’ `deinint` function to remove the observer from `NSNotificationCenter.defaultCenter()`.

## A Bug in the Simulator

Build and run. Hit Command-Shift-H then switch over to the settings app. Select the settings for the SettingsBundleDemo and… It’s blank.

This doesn’t happen on a device. Only the simulator. There is a workaround. It seems the simulator is still running your last iteration of your app. When you hit stop in Xcode it doesn’t stop the settings app. Click Command-Shift-HH to double-click the home button. Swipe up on the Settings app to kill the process. Start the Settings again, and settings refreshes itself. You’ll have a settings page again. Change the settings to this.

Go back to the Settings Bundle Demo. Our results show up this time.

That’s the basics of Settings Bundles. There are a few more advanced options such as child settings pages and coding the settings directly in XML. The charts above have the tags for XML and there is is the Root.plist code below in XML for your further exploration.

# The Whole Code

```//
//  ViewController.swift
//  SetttingsBundleDemo
//
//  Created by Steven Lipton on 3/11/16.
//

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var roomForCream: UISwitch!
@IBOutlet weak var drinkText: UITextField!
@IBOutlet weak var sizeSegment: UISegmentedControl!

deinit { //Not needed for iOS9 and above. ARC deals with the observer.
}

func registerSettingsBundle(){
let appDefaults = [String:AnyObject]()
NSUserDefaults.standardUserDefaults().registerDefaults(appDefaults)
//NSUserDefaults.standardUserDefaults().synchronize()
}

func updateDisplayFromDefaults(){

//Get the defaults
let defaults = NSUserDefaults.standardUserDefaults()

//Set the controls to the default values.
roomForCream.on = defaults.boolForKey("coffee_cream")
if let drink = defaults.stringForKey("coffee_type"){
drinkText.text = drink
} else{
drinkText.text = ""
}
sizeSegment.selectedSegmentIndex = defaults.integerForKey("coffee_size")
}

func defaultsChanged(){
updateDisplayFromDefaults()
}
@IBAction func updateDefaults(sender: AnyObject) {
updateDisplayFromDefaults()
}
registerSettingsBundle()
updateDisplayFromDefaults()
selector: "defaultsChanged",
object: nil)

}

// Dispose of any resources that can be recreated.
}

}

```

## Root.plist

While we did not discuss them here, you can make entries in XML to your property list. Here’s the property list for the demo in XML:

```<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Size</string>
<key>Key</key>
<string>coffee_size</string>
<key>DefaultValue</key>
<string>0</string>
<key>Values</key>
<array>
<integer>0</integer>
<integer>1</integer>
<integer>2</integer>
<integer>3</integer>
</array>
<key>Titles</key>
<array>
<string>Small</string>
<string>Medium</string>
<string>Large</string>
<string>Extra Large</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Room for cream</string>
<key>Key</key>
<string>coffee_cream</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Beverage of Choice</string>
<key>Key</key>
<string>coffee_type</string>
<key>DefaultValue</key>
<string>Coffee</string>
</dict>
</array>
</dict>
</plist>

```

# Using WatchOS2 Navigation in Swift

It’s rare to have a one controller application, even in something as small as the Apple watch. Multiple View Controllers, or Interface Controllers as they are called in WatchKit, need ways to move between controllers. WatchOS2 has a simplified version of the iOS navigation types. In this lesson we’ll explore these three types of navigation that are available for WatchOS: Page, Hierarchical, and Modal. You’ll find them summarized on this chart below

In this tutorial we’ll show all three programmatically and on the storyboard.

# Set Up the Project

Before starting the project, start the watch and phone simulators. If you do not have direct access to them, you might want to read the Before you Begin section in a earlier post.

Open Xcode if not already open. Create a new project and pick the iOS App with Watchkit App Watch project template.

You’ll get a configuration window like this:

Name the project WatchNavigationDemo using Swift as the language. Use a Universal device and uncheck Include Notification Scene as shown above. In the Navigator find these files:

## The Root Controller

Click on the Interface.storyboard in the WatchNavigationDemo WatchKit App group. You will get a blank watch scene with a watch controller and a notifications controller. Drag two buttons and a label to the controller. Set the background color to the system Dark Gray Color(#555555) for both buttons. In the attributes inspector, set one button’s alignment to Top Vertical Alignment, and the other button’s alignment to Bottom Vertical Alignment. Set the label’s text to Root and the font to Headline. Set the label’s vertical and horizontal alignment to Center.

Click the view controller icon. At the top of the attribute inspector, add a Title and Identity of Root

For each of our controllers we will add and identity and title. Title will set the title on the watch face. The Identifier names this controller programmatically. If you are only using segues, then you do not need it, but it is mandatory if you are programmatically calling your controllers. If you have neither a segue nor identifier you will get a warning error from Xcode that the controller is unreachable. With our controller done, it should look like this:

## The Page Controllers

Drag another interface controller to the storyboard. Change the background to Green(#AACC00). Add a button and a label. Set the vertical alignment for the button to Bottom. Set the background color to the system Dark Gray Color(#555555). Select the controller and change the Title and Identifier to Page 0. Set the label’s text to Page 0. Set the label’s vertical and horizontal alignment to Center.

Your controller should look like this:

Select the interface controller icon, then press Command-C to copy the controller. Deselect the controller by clicking on the background of the storyboard. Press Command-V to paste a copy of the controller. This pastes the controller directly on top of the original. It looks like the original controller is selected again. Drag this controller and you will find it is a copy.

Deselect, and press Command-V again. You now have three Page 0 controllers. Change the Identifier and Title of one copy to Page 1 and the other to Page 2. Arrange the controllers like this

## The Modal Controllers

Add two more controllers, which we’ll use as our modal controllers. Make one controller have a Red(#FF0000) background and the other a Blue(#0000FF) background. Set the Title and Identifier of the red modal to RedModal. Set the Title and Identifier of the blue modal to BlueModal.

Page navigation is similar to iOS page navigation  with pages sliding horizontally with a swipe. It is much simpler to set up than the iOS equivalent. All the glances on an apple watch are in a page sequence. If you don’t have a watch you can still see a quick example in the watch simulator. You can swipe up from the watch face to get to glances. Swipe left and right to see two glances.

Like most storyboard transitions between controllers we use segues. For page segues, We control-drag from one controller to another controller, then repeat to make the chain of controllers. Control-drag from the black background of Root to the green of Page 0. When you release the button, a Relationship Segue menu appears:

Select Next Page. A segue appears.

Control-drag from Page 0 to Page 1, repeating the process. Then do it again from Page 1 to Page 2. We have four pages connected together.

Build and run. You have four pages to scroll back and forth through.

Like navigation controllers in iOS, hierarchy navigation pushes the next controller to view through a selection device, such as a button. As the name implies you can branch in as any direction you want, unlike the linear page navigation. The settings app on the Apple Watch is an example of a hierarchy navigation you can see on both the watch and the simulator.

Delete all the segues on the storyboard. Select the top button on the root controller. Control-drag from the top button to the Page 0 controller. When you release the mouse button, you will get this menu:

Select Push. A segue appears between the controllers.

The process is almost the same as the page segues. The difference is you start your drag from a control, usually a button but it may be a group or table. Make a segue between the bottom button of Root and Page 1. Control drag from the bottom button of Root to Page 1. Select Push for the Action Segue type.

# Page and Hierarchy are Mutually Exclusive

Control-drag from Page 1 to Page 2 and make a page segue. Your storyboard should look like this.

Xcode does not put any warnings up, but what we just did is wrong. You cannot combine page and hierarchy segues. You can only use one or the other on the storyboard. With one exception, once you use one type or segue or the other. You are stuck in the project using that type of navigation only. However, nothing tells you this except the documentation. Clean the project with a Shift-Command-K, then Build and Run. Tap the top button, and you get Page 0.

At the top left of the watch is a back indicator which you tap to go back to root. If you try going to page 1 with the bottom button, there is no page indicator on the Page 1 to get us to page 2. Swipes don’t work either. The system will ignore any illegal segues.

Stop the app and delete the page segue. Control-drag from the button on Page 1 to Page 2 and select the `Push` segue. Clean, Build and Run. You get all three pages.

The last type of controller does not care what type is the one before it. Modal controllers can be called by both page and hierarchy controllers. While the two we’ve learned so far transition horizontally, modal controllers transition vertically. In the watch or simulator, swipe up on the watch face and you have a modal to the glances. The glances, as we discussed earlier, happen to be page navigation. Here’s an exception to the mutual exclusion between hierarchy and pages. If you have a hierarchy then segue to a modal, your modal can segue to pages. However it does not work the other way around. From a page, you cannot call a modal and then a hierarchy.

You set a Modal segue the same way as a hierarchical segue: from control to controller. Stop the app. From the Page 0 button, control-drag to the RedModal controller. Select Modal in the Action Segue menu

You get a segue between the two.

Control-drag from the Page 2 button to the BlueModal controller. Select a Modal action segue. From the BlueModal, control-drag to the RedModal. Select the Page relationship segue. Your storyboard should look like this:

Build and run. All the navigation works.

We’ve covered navigation on the storyboard. While the mutual exclusive part does provides some limits for building apps, there is enough flexibility to set up your entire app in the storyboard. It’s probably best to setup your applications in the story board, as many of the attributes of a controller are not accessible programmatically. However, many developers prefer programmatic navigation to segues. Sometimes the logic of the code dictates a more programmatic approach. There are three methods that call controllers directly, as shown in the chart above. We’ll discuss each as we code the controllers.

Press Command-N to make a new file. Make a new WatchOS Watchkit file named PageIntefaceController, subclassing `WKInterfaceController`. Save the file being careful to make sure the group is in the extension.

In the file that appears, add the following code.

```    var whichModal = "RedModal"
@IBOutlet var goModalOutlet: WKInterfaceButton!

@IBAction func goModalAction() {
presentControllerWithName(whichModal, context: nil)
}
```

In the action `goModalAction`, the method `presentViewControllerWithName:context: ` presents the modal controller with the identifier name from the storyboard. We’ve used a string variable `whichModal`, which we’ll use in a later iteration to switch between the blue and red modals. The second parameter `context`, sends data to the destination controller. We set this to `nil` to not use it. We’ll discuss this parameter in mmore detail below.

Select the InterfaceController.swift file. Add the follow code to the InterfaceController class

```@IBAction func topButton() {
pushControllerWithName("Page 0", context: nil)
}
@IBAction func bottomButton() {
let names = ["Page 2","Page 1","Page 0"]
presentControllerWithNames(names, contexts: nil)
}

```

The `bottomButton` action, contains the `presentControllerWithNames` method. This presents the page views. It has similar parameters to `presentControllerWithName`, with one change: instead of a single value it uses arrays. The array order is the order of the pages displayed. Our array is in the constant `names`, counting down pages instead of up as we have been doing. The `contexts` array has the corresponding context to in the names array. We are not using it yet, so we left that `nil`.

The action `topButton` has the method for the hierarchical segue `pushControllerWithName:context:` Like a navigation controller, it pushes the new interface into view. The parameters are identical to its modal brother.

Connect up your outlets and actions. Go back to the story board, and select the Page 0 controller. In the identity inspector, change the class to `PageInterfaceController`. Repeat for Page 1 and Page 2. Close the right panel inspector and open the assistant editor. Click on the Root Controller in the storyboard. Drag from the topButton action to the upper button. Drag from the bottomButton action to the bottom button.

Select the Page 0 controller. Connect the outlet and action to the button. Do the same for Page 1 and Page 2.

Clean, build and run. From the root menu, click the top button.

It goes to a hierarchical controller version of Page 0. Tap the button in Page 0 and we get the red modal.

Go back to the root, and tap the bottom button. You get a page controller starting with Page 2 and counts down pages to 0.

Tap any button on a controller goes to the red modal.

We seem to have broken the mutual exclusive nature of the page and hierarchy controllers. Programmatically,  there’s one more wrinkle. The system does not know which navigation you use until your first use of it on the root. In our app, we set that by the button pressed.

# Working with Contexts

Contexts pass data to a destination controller. In the modal and Hierarchical controllers it is a single `AnyObject?` For pages it is an optional array of `AnyObject`. Close the assistant editor, and go to the InterfaceController.swift file. Change the actions to this:

```    @IBAction func topButton() {
pushControllerWithName("Page 0", context: "BlueModal")
}
@IBAction func bottomButton() {
let names = ["Page 2","Page 1","Page 0"]
let contexts = ["RedModal","BlueModal","RedModal"]
presentControllerWithNames(names, contexts: contexts)
}
```

In `topButton` we pass a string as a context. In `bottomButton` we added a string array `contexts` that will pass the string RedModal for Page 0 and 2 and a BlueModal for page 1.

Go to the `PageInterfaceController` code. Change the `awakeWithContext` method to this:

```override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
if let newContext = context{
whichModal = newContext as! String
goModalOutlet.setTitle(whichModal)
}
}
```

The `awakeWithContext` method is the equivalent to `viewDidLoad` in iOS, except it receives a context. We can use that context to set up the class. First optionally chain the context’s value. Then assign it, downcasting appropriately. I’m setting which modal we will use this way, and also setting the button’s title to tell you where you are going.

Build and run. Select the bottom button and you will see the contexts changing the page controllers.

What if we wanted to make a more elegant title for the button? A common way of passing more than one parameter in the context is to use a dictionary. Change InterfaceController’s actions to this:

```@IBAction func topButton() {
let context:[String:AnyObject] = ["Name":"BlueModal","Title":"Blue"]
pushControllerWithName("Page 0", context: context)
}
@IBAction func bottomButton() {
let names = ["Page 2","Page 1","Page 0"]
let contexts:[[String:AnyObject]] = [
["Name":"RedModal","Title":"Red"],
["Name":"BlueModal","Title":"Blue"],
["Name":"RedModal","Title":"Red"]
]
presentControllerWithNames(names, contexts: contexts)
}
```

Using a dictionary of type `[String:AnyObject]`, I pass two strings to the array. I could use a `[String:String]`, but I want to demonstrate the more generic case where you could use more than one type of data in the dictionary. Go to `PageInterfaceController`. Change `awakeWithContext` like this:

```    override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
if let newContext = context{
let contextDictionary = newContext as! [String:AnyObject]
whichModal = contextDictionary["Name"] as! String
let title = contextDictionary["Title"] as! String
goModalOutlet.setTitle(title)
}
}
```

We changed the code to read a dictionary instead of a single value. You could do the same with a class or struct as well, though dictionaries are nicely temporary in comparison. Build and run. Click the top button and you find the Blue titled button

Go Back to Root, then click the bottom button, we have a Red button

## Contexts with Segues

Watchkit also has a equivalent to `prepareForSegue` for passing data when you use a storyboard segue. Like `prepareForSegue`, you override the method. For modals and hierarchy there is the method For pages there is the to accommodate the array of contexts. Go to the storyboard and add a push segue between Root and Page 0

In the attributes inspector, set the Identifier for the segue to Page0. Go to `InterfaceController`. Comment out the code in `topButton`

```@IBAction func topButton() {
//let context:[String:AnyObject] = ["Name":"BlueModal","Title":"Blue"]
//pushControllerWithName("Page 0", context: context)
}
```

```override func contextForSegueWithIdentifier(segueIdentifier: String) -> AnyObject? {

if segueIdentifier == "Page0"{
let context:[String:AnyObject] = ["Name":"BlueModal","Title":"Blue"]
return context
} else {
return nil
}
}
```

The `contextForSegueWithIdentifier` works similar to `prepareForSegue`. Take  `segueIdentifier` and do what you need to set up the destination controller for that specific segue. The difference is we return the context, instead of setting a properties of the destination controller directly. For pages, we do the same thing using arrays and `contextsForSegueWithIdentifier`

Clean, build and run. Tap the top button on Root You should see no difference between the last run and this one.

That is most of what you need to know about navigation. There are two or three more thing you might want to know such as dismissals and delegates. We’ll cover those next time as we delve into using tables in WatchOS2.

# The Whole Code

## InterfaceController.swift

```//
//  InterfaceController.swift
//
//  Created by Steven Lipton on 3/1/16.
//

import WatchKit
import Foundation

class InterfaceController: WKInterfaceController {

@IBAction func topButton() {
// code commented out for using segues and context
// code for hierachy (push) segues
//let context:[String:AnyObject] = ["Name":"BlueModal","Title":"Blue"]
//pushControllerWithName("Page 0", context: context)

}
override func contextForSegueWithIdentifier(segueIdentifier: String) -> AnyObject? {
// the prepareForsegue of WatchOS for modals and push
// use contextsForSegueWithIdentifier for pages
if segueIdentifier == "Page0"{
let context:[String:AnyObject] = ["Name":"BlueModal","Title":"Blue"]
return context
} else {
return nil
}

}
@IBAction func bottomButton() {
// A Page controller sequence with a dictionary as a context.
let names = ["Page 2","Page 1","Page 0"]
let contexts:[[String:AnyObject]] = [
["Name":"RedModal","Title":"Red"],
["Name":"BlueModal","Title":"Blue"],
["Name":"RedModal","Title":"Red"]
]
presentControllerWithNames(names, contexts: contexts)
}

}

```

## PageInterfaceController.swift

```//
//  PageInterfaceController.swift
//
//  Created by Steven Lipton on 3/3/16.
//

import WatchKit
import Foundation

class PageInterfaceController: WKInterfaceController {
var whichModal = "RedModal"
@IBOutlet var goModalOutlet: WKInterfaceButton!

@IBAction func goModalAction() {
//present a modal controller
presentControllerWithName(whichModal, context: nil)
}
override func awakeWithContext(context: AnyObject?) {
// has a parameter which has the context sent to the controller
// So you can set the controller up
// we use a dictionary  of [String:AnyObject]
super.awakeWithContext(context)
if let newContext = context{
let contextDictionary = newContext as! [String:AnyObject]
whichModal = contextDictionary["Name"] as! String
let title = contextDictionary["Title"] as! String
goModalOutlet.setTitle(title)
}
}
}

```