Category Archives: Swift

What Do you do with Any?

There’s been a major change to Swift 3.0 That many people might find a little disturbing in code, and others may have no idea what it is. In one sense that’s the idea. Apple changed AnyObject to Any in Swift 3.0. This three-letter word is an extremely powerful feature,a backbone of many functions and classes, and the core of watchOS’s way of transmitting data from one controller to another.

The class Any is the object that is anything. It is generic. You learned early in your coding lessons that everything has a type and everything gets assigned a type like this:

let radius = 5.0   // a Double
var diameter:Int = 10  //an Int
var pizzaTopping = "Pepperoni"  //a string

Functions need a type in their parameters too. For example, there is this function

func pizzaArea(radius:Double)-> Double {
let area = radius * radius * M_PI
return area
}

Since everything needs a type to work right, a function assigning something like this might seem a little odd.

func pizzaSize(context:Any) -> Double {
    var size = 0.0
    let radius = context as! Double
    size = radius * radius * M_PI
    return size
}

If you tried

print(pizzaSize(context: 5.0))

You would get a result around 78.54.

Any really isnt totally generic. It’s a place holder because there are times when writing code, you have to be vague in how you add a parameter. Look closely at pizzaSize(context:Any). You’ll see this is identical to pizzaArea(radius:Double) but I set the type in my code instead of in the parameter. To set the type, I downcast the type Any to Double using as!. Another example

let myAnyType:Any = 12.0
let myDoubleType:Double = myAnyType as! Double
print(myDoubleType)

Why would you want to delay typing? Because you, or some other developer such as Apple wrote some code and has no idea how you are going to use that code. Consider the following class

class PizzaGeometry{
init(context:Any){
self.awake(context: context)
}
func awake(context:Any){}
}

This code by itself does nothing but call an empty function awake(context:) and have an empty function pizzaArea. But we could subclass this to do areas of pizzas for both integers and doubles by awake(context:).

class PizzaAreaInt:PizzaGeometry{
    var radius:Int = 0
    override func awake(context: Any) {
        radius = context as! Int
    }
    func pizzaArea() {
        print (radius * radius * 3)
    }
}

class PizzaAreaDouble:PizzaGeometry{
    var radius:Double = 0.0
    override func awake(context:Any){
        radius = context as! Double
    }
    func pizzaArea(){
        print(M_PI * radius * radius )
    }
}

I couldn’t have done that had I set the type in PizzaGeometery. Most of you are probably iOS developers and haven’t touched watchOS yet. However in Apple’s obsession about keeping things simple in watchOS, PizzaGeometery is the skeletal definition of a view controller , named WKInterfaceController class in watchOS. watchOS passes data between view controllers directly without, like iOS,  referencing the destination in prepare(forSegue:) or initializing the destination class and setting properties. It sends those values as a context, and lets the awake(withContext context:any) deal with it. Developers unpack the context for the controller they are currently writing by overriding awake. However Any is not just a watchOS thing. iOS uses it too, and one form of this shows up all over the place: Dictionaries

Area for circles is a single property. What if we wanted to make a class for more than one property in PizzaGeometery?  That’s where dictionaries come in. In Swift, you can define a dictionary of type [String:Any].  What does that do? It means you can have an identifier name as a key and place its value — no matter the type — as a the value. for example:

let rectanglePizzaDictionary:[String:Any] = 
    ["width":10,"length":12,"height":1.2]

I can unpack a dictionary like that in my Subclass

class PizzaRectangle:PizzaGeometry{
    var height:Double = 0.0
    var width:Int = 0
    var length:Int = 0
    override func awake(context: Any) {
        let contextDictionary = context as! [String:Any]
        height = contextDictionary["height"] as! Double
        width = contextDictionary["width"] as! Int
        length = contextDictionary["length"] as! Int
    }
    func pizzaArea(){
        print(width * length)
    }
    func pizzaVolume(){
        print (width * length * Int(height))
    }
}

I unpacked twice. First I unpacked to the type [String:Any]. Then I unpacked the entries in the dictionary.  Here’s the one issue you’ll need to be careful with here. For simplicity I didn’t error check, but if any of these values are not what I expect for the dictionary the app will crash. You need error checking here and maybe even more importantly, good documentation of the possible dictionary entries. As iOS developers this is going to be a big problem since a lot of methods in UIKit use this dictionary format to send information back to you as a developer. Apple used to be worse at this, but their current documentation system seems to have solved a lot of this. For example one of the excruciating examples of this is the UIImagePickerControllerDelegate method  imagePickerController(_:didFinishPickingMediaWithInfo:). There’s now a link in the documentation, but for a while it was a very hard search to find the keys and value in the info dictionary.

Any is very helpful. Apple uses it often once you start looking for it. Any means “I don’t know what supposed to go in here, could you set it up for me” when it comes to values. Dictionaries of [String:Any] exist all over the API, often in delegates and closures. watchOS makes it the way to pass values between interface controllers. What at first glance looks like an empty generic container is really a powerful way of deferring type until necessary, making for a more flexible programming environment.

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
    func roundArea(radius:Double) -> Double{
        return M_PI * radius * radius
    }
    //volume of a round pizza
    func roundVolume(height:Double, radius:Double ) -> Double{
        return roundArea(radius: radius) * height
    }

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
    return M_PI * radius * radius / slices
}

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
            return radius * radius * M_PI
 }
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
    return M_PI * radius * radius 
}
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) 
    {(radius,placemarker)->Double in
        return M_PI * radius * radius
    }
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 iconalignment 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:

center alignment

Click Add 2 constraints.  Select the Label. Title it Results.  Click the pin icon pinMenuButton 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.

2016-09-02_07-07-01

Click Add 3 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.
     let alert = UIAlertController(
         title: "Alert",
         message: "Volume is \(volume)",
         preferredStyle: .alert)
   

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:

   
let clearAction = UIAlertAction(
    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:

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

Add the actions to the alert

alert.addAction(clearAction)
alert.addAction(doubleAction)
alert.addAction(cancelAction)

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.

 
present(alert, animated: true, completion: 
{()->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:

2016-09-12_06-03-57

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

2016-09-12_06-04-38

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
    func roundArea(radius:Double) -> Double{
        return M_PI * radius * radius
    }
    //volume of a round pizza
    func roundVolume(height:Double, radius:Double ) -> Double{
        return roundArea(radius: radius) * height
    }
    var volume = roundVolume(height:2,radius:6)
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
    return M_PI * radius * radius / slices
}
//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
let circleArea = {(radius:Double, placeMarker:Double) -> Double in return M_PI * radius * radius }
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) {
     (radius,placemarker)->Double in
          return M_PI * radius * radius
}

//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
         
}

The ClosureDemo Alert project

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.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

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.
        let alert = UIAlertController(
            title: "Alert",
            message: "Volume is \(volume)",
            preferredStyle: .alert)
        
        let clearAction = UIAlertAction(
            title: "Clear", style: .destructive,
            handler: {(action)->() in
                self.volume = 0
                self.resultLabel.text = "\(self.volume)"
        })
        
        let doubleAction = UIAlertAction(
            title: "Double",
            style: .default,
            handler: {(action)->() in
                self.volume *= 2
                self.resultLabel.text = "\(self.volume)"
        })
        let cancelAction = UIAlertAction(
            title: "Cancel",
            style: .cancel,
            handler:{(action)->() in
                self.resultLabel.text = "\(self.volume)"
        })
        
        
        alert.addAction(clearAction)
        alert.addAction(doubleAction)
        alert.addAction(cancelAction)
        present(alert, animated: true, completion: {()->Void in
            print ("In present Handler")
        })
        print ("Outside Handler")
        
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    
}

Why Does Apple Need Delegates?

In my post Why do we need delegates, I explained one major developer use of delegates: moving data from a destination view controller back to the controller that presented it or pushed it onto the stack. This is not the only use of delegates. Apple uses it often  in APIs. In this theoretical lesson we’ll discuss what they doing under-the-hood and why. We’ll dissect the entire process, so you will understand what you are doing in your code.

The Basic Problem

Let’s start with a simple class, which if you want you can copy into a playground to try:

class SimpleClass{
    var array:[String] = ["A","B","C","D"]
    func printArray(){
        for string in array {
            if string.characters.count != 0{
                print(string)
            }else{
                print("Empty String")
            }
        }
    }
}

We use this class this way:

let simpleClass = SimpleClass()
simpleClass.printArray()

This class prints an array. When a developer writes this you have access to the methods and functions. If you wanted to re-write this to be more customizable, you could just change the source. You can assign different values to the array.
However, Apple (and sometimes developers) don’t want to you messing with their code. Apple will suspend your developer license for doing that to an API. Often Apple writes the code so you have no access to things like array at all. Suppose our code changes to this:

class SimpleClass{
    func printArray(){
        let array:[String] = ["A","B","C","D"]
        for string in array {
            if string.characters.count != 0{
                print(string)
            }else{
                print("Empty String")
            }
        }
    }
}

Here’s the problem: You want to format string and set the values in array. You just can’t since you have no access to them.

Adding a Protocol

What Apple does for these customization situations is write protocols for the class. You’ll find two different names of this protocol. For getting data, you’ll find a protocol called a data source. For changing data or reacting to events, you’ll find a delegate.

Adding a Data Source

A data source is a function that defines the data in a class. You write the function to return the data you want to use. For example, we could add the following protocol for array

protocol SimpleClassDataSource{
    func array() -> [String]
}

We could then change our code to this:

class SimpleClass{
    var dataSource:SimpleClassDataSource! = nil
    func printArray(){
        let array:[String] = dataSource.array()
        for string in array {
            if string.characters.count != 0{
                print(string)
            }else{
                print("Empty String")
            }
        }
    }
}

Line 2 creates a property dataSource which has an optional value of SimpleClassDataSource as its type. In line 4, the code calls dataSource function array to get the data for the array.

Of course, there is no data yet. That’s in the class that will use SimpleClass and adopts the SimpleClassDataSource protocol. Suppose we had this class:

class PrintingDoughnuts{
}

We could use our simple class to print the doughnuts. First, add a constant simpleClass, and an initializer to run it.

class PrintingDoughnuts{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.printArray()
    }
}

If we try running this code, with PrintingDoughnuts() we get an error:
fatal error: unexpectedly found nil while unwrapping an Optional value

The protocol is set to nil, and thus crashes. We still need to assign the data we want. First, we adopt the protocol,

class PrintingDoughnuts:SimpleClassDataSource{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.printArray()
    }  
}

Then we tell simpleClass to find our implementation of array inside PrintingDoughnuts, by assigning self to the data source.

class PrintingDoughnuts:SimpleClassDataSource{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.dataSource = self
        simpleClass.printArray()
    }
}

Finally, we implement our version of array

class PrintingDoughnuts:SimpleClassDataSource{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.dataSource = self
        simpleClass.printArray()
    }
    
    func array() -> [String] {
        return ["Boston Cream","Cruller","Old Fashioned","","Frosted"]
    }
}

I just assigned a literal array here, but I could have just as easily called an external XML File to download data, or calculated some values. I can do anything here that returns a string array. That’s the power of a data source: While the class does not change I can do anything I want with it.

If I go and run this code by PrintingDoughnuts(), I get this output:

Boston Cream
Cruller
Old Fashioned
Empty String
Frosted

You can think of data sources setting properties otherwise inaccessible by coding, because someone made it impossible to get at the property directly.

Adding Delegates

While data sources are for properties, delegates are for methods. If you want to do something because of a change in your values or with your data you find those in a delegate. The developer of SimpleClass for example might use a delegate to change string and to react to a blank string in the array. The protocol for that might look like this:

protocol SimpleClassDelegate{
    func format(string:String)->String
    func handleEmptyString()
}

The SimpleClass would use it like this:

class SimpleClass{
    var dataSource:SimpleClassDataSource! = nil
    var delegate:SimpleClassDelegate! = nil
    func printArray(){
        let array:[String] = dataSource.array()
        for string in array {
            if string.characters.count != 0{
                print(delegate.format(string: string))
            }else{
                delegate.handleEmptyString()
            }
        }
    }
}

Line two creates an optional property called delegate with type SimpleClassDelegate and sets it to nil. Lines 8 and 10 use the methods of delegate. Again we don’t know what those methods are yet. That happens in the class that adopts the protocol.

Just like the data source, we’d implement the adoption of the protocol like this:

class PrintingDoughnuts:SimpleClassDataSource, SimpleClassDelegate{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.dataSource = self
        simpleClass.delegate = self
        simpleClass.printArray()
    }
    // data source
    func array() -> [String] {
        return ["Boston Cream","Cruller","Old Fashioned","","Frosted"]
    }
    // delegates for self
    func format(string: String) -> String {
        return "Yummy " + string + " Doughnut"
    }
    func handleEmptyString() {
        print("Waaah!! No Doughnut!")
    }
}

Like the data source, adopt the protocol in line 1. Tell delegate in line 6 that the delegate methods can be found in this class. Lines 13 through 19 are those delegate methods.

Our output changes:

Yummy Boston Cream Doughnut
Yummy Cruller Doughnut
Yummy Old Fashioned Doughnut
Waaah!! No Doughnut!
Yummy Frosted Doughnut

External Implementation of a Protocol

One more thing about line 5 and 6. We set dataSource and delegate to self. In most cases, this is what you will do, because you want to write the required methods in the same class as you use them. However, this is not always the case. If you will use the same methods for multiple classes you may make a separate class like this:

class DoughnutDelegateMethods:SimpleClassDelegate{
    // delegates
    func format(string: String) -> String {
        return "Very Yummy " + string + " Doughnut"
    }
    func handleEmptyString() {
        print("**Waaah!! No Doughnut!**")
    }
}

We’ve adopted the protocol, and implement the required methods in this separate class with a few changes to tell the difference.
We can change line 6 of PrintingDoughnuts to this:

simpleClass.delegate = DoughnutDelegateMethods

Now the delegate is reading the methods from the DoughnutDelegateMethods class:

Very Yummy Boston Cream Doughnut
Very Yummy Cruller Doughnut
Very Yummy Old Fashioned Doughnut
**Waaah!! No Doughnut!**
Very Yummy Frosted Doughnut

We can now use the same delegate method in another class for Firecakes Doughnuts, an artisan doughnut shop in Chicago:

class PrintingFirecakes:SimpleClassDataSource{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.dataSource = self
        simpleClass.delegate = DoughnutDelegateMethods()
        simpleClass.printArray()
    }
    // data source
    func array() -> [String] {
        return ["Triple Valrhona Chocolate Cake","Maple Glazed Pineapple & Bacon","Butterscotch Praline","","Malted Milk Ball"]
    }
}

This time we only adopted the data source.We only need to adopt the delegate when writing the delegate methods. For our delegate we told the system to find it in the class DoughnutDelegateMethods. Since they are not in this class we don’t adopt them. Running the PrintingFirecakes() in a playground gets us a list of these doughnuts too:

Very Yummy Triple Valrhona Chocolate Cake Doughnut
Very Yummy Maple Glazed Pineapple & Bacon Doughnut
Very Yummy Butterscotch Praline Doughnut
**Waaah!! No Doughnut!**
Very Yummy Malted Milk Ball Doughnut

How Apple’s API’s Use This

With that look under the hood of API delegates and data sources, we can look at what you need to do for any API that has delegates. Some have required delegates, such as the UITableView, UIImagePickerController and CLCoreLocationManager classes. In Swift, UITableview's delegate and data source are so important, Apple bundled them into the Swift version of the class, while you do have to adopt them in Objective-C.

In a non working example lets look at CLCoreLocationManager. For an API delegate or data source we have three things to do

  1. Adopt the delegate
  2. Set the location of the delegate’s method implementation, usually self to say “within this class”
  3. Implement the delegate methods

Here’s a fragment of code to show what it would look like. By now you should understand what Apple is doing. All of the methods that return values from the GPS are delegate methods found in CLLocationManagerDelegate. When one of those events occurs, that delegate method gets called. If you want to do something at that event you implement that delegate method.

/*
//
// This shoud really be run on a device, not the playground
// commented out as a non working example, which is missing functional parts
 
import MapKit
// #1- adopt the delegate
class WhereAmI:NSObject,CLLocationManagerDelegate{
let myLocationManager = CLLocationManager()
    override init(){
        super.init()
 
 // #2 - set the delegate implementation to this class
        myLocationManager.delegate = self      
    }
 //#3 - Use delegate functions
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let myLocation = locations.first
        print ("my latitude = \(myLocation?.coordinate.latitude)")
        print ("my longitude = \(myLocation?.coordinate.longitude)")
    }
}

WhereAmI()
*/

The Whole Code

This was an under the hood explanation of something developers use often. You still might want to play with the code I wrote. You can cut and paste the code below into an Apple playground, or click here to run the code in the IBM swift sandbox.

//:
//: An example of API use of delegates and data sources
//: (c)Steven Lipton (makeapppie.com) July 2016
//: See http://makeapppie.com for explanation

import UIKit
//
//: A data source protocol
//
protocol SimpleClassDataSource{
    func array() -> [String]
}
//
//: A delegate protocol
//
protocol SimpleClassDelegate{
    func format(string:String)->String
    func handleEmptyString()
}
//
//:A simple class that uses the protocols 
//
class SimpleClass{
    var dataSource:SimpleClassDataSource! = nil
    var delegate:SimpleClassDelegate! = nil
    func printArray(){
        let array:[String] = dataSource.array()
        for string in array {
            if string.characters.count != 0{
                print(delegate.format(string: string))
            }else{
                delegate.handleEmptyString()
            }
        }
    }
}
//
//: The first example class that uses SimpleClass
//
class PrintingDoughnuts:SimpleClassDataSource, SimpleClassDelegate{
    let simpleClass = SimpleClass()
    
    init() {
    //If we want to implement the protocol in this class, we use self
        simpleClass.dataSource = self
        simpleClass.delegate = self
    //If we want to implement the protocol in an external class
        //simpleClass.delegate = DoughnutDelegateMethods()
        simpleClass.printArray()
    }
    // data source implementation
    func array() -> [String] {
        return ["Boston Cream","Cruller","Old Fashioned","","Frosted"]
    }
    // delegate implementations
    func format(string: String) -> String {
        return "Yummy " + string + " Doughnut"
    }
    func handleEmptyString() {
        print("Waaah!! No Doughnut!")
    }
}
//
//: An external implementaion of the delegate methods, used
//: when sharing the implementaion between classes
//
class DoughnutDelegateMethods:SimpleClassDelegate{
    // delegates
    func format(string: String) -> String {
        return "Very Yummy " + string + " Doughnut"
    }
    func handleEmptyString() {
        print("**Waaah!! No Doughnut!**")
    }
}
//
//: An eaxmple of a second method sharing the delegate implementation
//
class PrintingFirecakes:SimpleClassDataSource{
    let simpleClass = SimpleClass()
    
    init() {
        simpleClass.dataSource = self
        simpleClass.delegate = DoughnutDelegateMethods()
        simpleClass.printArray()
    }
    // data source
    func array() -> [String] {
        return ["Triple Valrhona Chocolate Cake","Maple Glazed Pineapple & Bacon","Butterscotch Praline","","Malted Milk Ball"]
    }
}

 let doughnutList = PrintingDoughnuts()
 let fireCakeList = PrintingFirecakes()
/*
 
//
//: An example of CLLocationManager using delegates 
//: This shoud really be run on a device, not the playground
//: commented out as a non working example, which is missing functional parts
// 
import MapKit
//: #1- adopt the delegate
class WhereAmI:NSObject,CLLocationManagerDelegate{
let myLocationManager = CLLocationManager()
    override init(){
        super.init()
 
 //: #2 - set the delegate implementation to this class
        myLocationManager.delegate = self      
    }
 //: #3 - implement delegate functions
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let myLocation = locations.first
        print ("my latitude = \(myLocation?.coordinate.latitude)")
        print ("my longitude = \(myLocation?.coordinate.longitude)")
    }
}

let whereAmI = WhereAmI()
*/

Adding Modal Views and Popovers in Swift 3.0

Modal views are one of the fundamental ways to present view controllers. Some early applications on the iPhone were completely modal views — some still do.  Modals do not do their own housekeeping like navigation controllers or tab controllers, so they are not as efficient for the backbone of your application. They need the user’s attention and suspend everything else in your UI,  making them good for settings pages and the like.

Developed originally for the iPad, Popovers are similar to modals. They are a type of view controller that requires user attention. Modals take over the window, which on the bigger real estate of the iPad, is often a waste of space. Popovers use limited space and place a smaller view on top of the main window.

Apple in iOS8 merged popovers and alerts into modals to create the current adaptive layout system. Instead of the developer having to write different code for different devices, adaptive layout does the heavy lifting and the developer writes code once. In this lesson we’ll show several ways to add popovers and modals to different devices.

Set Up the Project

First we’ll need a new project. In Xcode 6, go to File>New>Project… or hit Command-Shift-N. Create a Single-View project called Swift3PizzaPopover, set the language to Swift. Set the device to Universal, then save the project to a place you’d like.
We will be using some photos. You can use your own, here are the two I used:
pizza_sm

popover_sm

These are the full-size images. Right-Click and save the images from your browser to some folder or your desktop on your Mac. In Xcode, click on the Assets.xcassets, and from the folder you saved the images drag them into the assets work area.

2016-06-29_05-37-20

Go into the storyboard. In the lower left hand side of the storyboard, you  will find the Class Size Preview Button with the words View as: iPhone6s(wC hR)

2016-06-28_05-29-33

Click this button to show the preview bar.

2016-06-28_05-39-43

We’ll skip auto layout in this lesson and use some drag and drop layout. To make sure our controls show up on all devices we’ll lay out for the smallest device. Select the iPhone 4s device, leaving the orientation in portrait.

2016-06-29_06-02-06

 

Click the color strip in the Background Color property for the controller, In the color picker that appears, click the sliders button if not already pressed, and in the drop down change to RGB Color.

2016-06-29_06-21-50

Change the view’s background color to Hex Color #FCE8E5. Drag four buttons on the scene. On the two top buttons, remove the title and add the pizza and popover images we just loaded as the button image. On the button below the pizza image button, change the title to Pizza Modal and set the font size to 26 points. Change the title of the button to Popover and set the font size to 26 points. Arrange the buttons to something like this:

2016-06-29_06-04-54

Now drag two more view controllers out. Change each to have different background colors. I used  a background color of #D337C8  for one and the other #FDDB28

2016-06-29_06-13-36

Change to the media library by selecting the clip of film in the lower right.

2016-06-29_06-08-04

In the first view controller, add an UImageView of the pizza by dragging the pizza image to one of the new controllers. Do the same with the popover image in the other controller.

2016-06-29_06-16-54

Click the square-in-circle button to go back to the object library, and drag a label to each of these view controllers. Change the text to read BBQ Chicken Pizza and Cheddar Popover respectively. Make the font for each 20 points.

Unlike Navigation controllers, you need to explicitly dismiss a modal controller.  We’ll need a Done button. Add a button to the modal view, labeled Done at 26 points font size. Make the background Red(#FF0000) with  White(#FFFFFF) text. Popovers dismiss when anywhere outside the popover gets a touch event. However we’ll find that popovers aren’t always popovers, so cut and paste this button to the popover view.

When done, your two controllers should look like this:

2016-06-29_06-32-21

Hit Command-N to get a New File. Under iOS click Source> Cocoa Touch Class. Create a new view controller subclassing UIViewController called PizzaModalViewController. Repeat and make a UIViewController subclass called PopoverViewController Assign the subclasses to their respective view controllers using the identity inspector. Your  finished story board should look like this:

2016-06-29_06-39-06

Using Segues Directly

The easiest way of using segues and modals is to directly connect a segue from the button to the view controller. In the storyboard, control-drag from the pizza picture button  to the PizzaModalVC view. In the menu that appears, select Present Modally.

2016-06-29_06-44-57

Click on the circle for the segue and set the identifier to Pizza.

2016-06-29_07-03-41

Now for the popover, control-drag from the popover photo to the PopoverVC view. Select Present as Popover.

2016-06-29_06-48-03

Select the segue, then set the identifier to Popover in the attributes inspector.

2016-06-29_06-50-03

Select an iPad Air 2 in the simulator. Build and run.

2016-06-29_06-53-27

Click on the Popover picture. You will get this:

2016-06-29_06-54-37

Tap anywhere but the popover and the popover disappears. Tap the pizza picture, and the pizza appears from the bottom. However, we can’t get rid of it.

2016-06-29_06-56-03

We did not yet make the dismissal code. Stop the simulator, and go back to the storyboard. Bring up the assistant editor, and select the PizzaModalVC view. Connect the Done button to the view controller code by selecting the Done button and then control dragging the button to the view controller.  Select an action for the connection as a UIButton. Call this pizzaModalDone Do the same for the popover, calling the method popoverDone.

In the PizzaModalVC class add the following to pizzaModalDone:

@IBAction func pizzaModalDone(_ sender: UIButton) {
    dismiss(animated: true, completion: nil)
}

In the PopoverVC class, add the following to popoverDone:

@IBAction func popoverDone(_ sender: UIButton) {
    dismiss(animated: true, completion: nil)
}

We dismiss any modal view controller with dismiss.  It is a method of the modal view controller, hence we are calling it from within the class. It has two arguments. The first indicates if an animation should   accompany dismissal. This is the usual way to dismiss, However for speed when dismissing a modal view behind another view, you can set this to false. The second argument is a closure if you need to do anything after successfully dismissing the view controller. Generally I leave it nil.

Build and run. Now both Done buttons work, and well as clicking in the shaded area outside the popover.

Presenting a Segue Programmatically

Go back to the storyboard. In our main view controller add this above viewDidLoad():

@IBAction func openPizzaModal(_ sender: UIButton) {
        performSegue(withIdentifier:"Pizza", sender: self)
    }
    @IBAction func openPopover(_ sender:UIButton){
        performSegue(withIdentifier:"Popover", sender: self)
    }

Connect the openPizzaModal(sender:) to the Pizza Modal button and the openPoppover(sender:) to the Popover button by dragging from the circle to the correct button. Build and run. Now you can use the bottom text buttons as well as the photos. Line 2 and 5 use the performSegue(withIdentifier:) method. When we set up our segues we gave them identifiers. We’ve used that identifer to call the segue. If you want all your buttons to use segues programmatically, control drag from the source view controller icon in the storyboard to the destination view controller.

Programmatically Presenting a Modal View Controller from the Storyboard

When using a storyboard, we can use the storyboard identifier to do that.  Go to the story board and select the pizza view controller. In the Identity inspector change the Storyboard ID to Pizza

2016-06-29_08-13-46

We’ll use this identifier to call our view controller from the storyboard. Add another button Pizza Prog with 26 point type to the root controller next to the Pizza Modal Button

2016-06-29_08-18-00

Open the assistant editor and control drag the new button tot he code. Make another action openPizzaProgModal in the ViewController class.

In ViewController.swift and change openPizzaProgModal to this:

@IBAction func openPizzaProgModal(_ sender: UIButton) {
    let vc = (
        storyboard?.instantiateViewController(
        withIdentifier: "Pizza")
    )!
    vc.view.backgroundColor = UIColor.orange()
    vc.modalTransitionStyle = .crossDissolve
    present(vc, animated: true, completion: nil)
}

Line two gets the view controller from the storyboard using the Storyboard Identifier we set up. If these two do not not match exactly you will get a fatal error.

Line 8 is the core of this. The present method presents the modal view, with animation and no completion handler.  It’s sort of the bracket to the dismiss method, with almost the same arguments. There is one difference. In dismiss, the object dismissed calls dismiss. In present, the current view controller calls present, and the first argument is the view controller to be presented.  Pretty much all presentation of view controllers look exactly like this.

When using present, there is no prepare(for segue:)  equivalent, which you would have with performSegue or running from a storyboard segue.  Once we have the view controller,  we change its properties directly, such as changing the background to orange in line 6. We can also change the transition to a cross dissolve, using the property modaltransitionStyle.

Build and run. Select the Pizza Modal button and you will see our flip transition and a different layout than the segue version.

2016-06-29_12-00-21

Programmatically Presenting a Modal View

The present method can be used with any view controller. If you made your own programmatic one, you need only an instance of the view controller to present it.

Press Command-N and add a new Cocoa Touch Class named PizzaModalProgViewController subclassing UIViewController.

I won’t go into details about this code, but suffice it to say it creates a view controller with a blue Done button, a label, and an image.

class PizzaModalProgViewController: UIViewController {
    let dismissButton:UIButton! = UIButton(type:.custom)
    var imageName = "pizza_sm"
    var text = "BBQ Chicken Pizza!!!!"
    
    let myLabel = UILabel()
    
    func pizzaDidFinish(){
        dismiss(animated: true, completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Build a programmatic view
        
        //Set the Background color of the view.
        view.backgroundColor = UIColor(
            red: 0.8,
            green: 0.6,
            blue: 0.3,
            alpha: 1.0)
        // Add the image to the view
            let myImage:UIImage! = UIImage(named: imageName)
            let myImageView = UIImageView(image: myImage)
            myImageView.frame = view.frame
            myImageView.frame = CGRect(
                x: 10,
                y: 10,
                width: 200,
                height: 200)
            view.addSubview(myImageView)
        // Add the label to the view
        myLabel.text = text
        myLabel.frame = CGRect(
            x: 220,
            y: 10,
            width: 300,
            height: 150)
        myLabel.font = UIFont(
            name: "Helvetica",
            size: 24)
        myLabel.textAlignment = .left
        view.addSubview(myLabel)
        
    //Add the Done button to the view.
        let normal = UIControlState(rawValue: 0) //.normal doesn't exist in beta. workaround
        dismissButton.setTitle("Done", for: normal)
        dismissButton.setTitleColor(UIColor.white, for: normal)
        dismissButton.backgroundColor = UIColor.blue
        dismissButton.titleLabel!.font = UIFont(
            name: "Helvetica",
            size: 24)
        dismissButton.titleLabel?.textAlignment = .left
        dismissButton.frame = CGRect(
            x:10,
            y:275,
            width:400,
            height:50)
        dismissButton.addTarget(self,action: #selector(self.pizzaDidFinish),for: .touchUpInside)
        view.addSubview(dismissButton)
    }
}

Go back to ViewController.swift and the openPizzaModal action. Comment out the code for the storyboard and add a few new lines of code above it.

@IBAction func openPizzaProgModal(_ sender: UIButton) {
   //using a view controller
    let vc = PizzaModalProgViewController()
    vc.modalTransitionStyle = .partialCurl
    present(vc, animated: true, completion: nil)
 
/* //using a story board
    let vc = (storyboard?.instantiateViewController(
        withIdentifier: "Pizza"))!
    vc.view.backgroundColor = UIColor.orange
    vc.modalTransitionStyle = .crossDissolve
    present(vc, animated: true, completion: nil)
 */       
}

Since the present method uses a view controller, line 3 gets an instance of one. Line 4 changes the transition style again, this time to a page curl transition. Line 5 presents the controller, looking identical to line 12 when we presented a view controller from the storyboard..

Build and run. Click the Pizza Prog button to get a different modal than before.

2016-06-30_05-38-17

Programmatically Presenting a Popover

How to present a popover is similar to calling a modal programmatically. There are a few differences however. Change the view controller method openPopover as follows, commenting out the previous code:

@IBAction func openPopover(_ sender:UIButton){
    //performSegue(withIdentifier:"Popover", sender: self)
    let vc = PizzaModalProgViewController()
    //change properties of the view controller
    vc.text = "Cheesy!!"
    vc.imageName = "popover_sm"
    vc.view.backgroundColor = UIColor.yellow
    //present from a view and rect
    vc.modalPresentationStyle = .popover //presentation style
    present(vc, animated: true, completion: nil)
    vc.popoverPresentationController?.sourceView = view
    vc.popoverPresentationController?.sourceRect = sender.frame
}

Line three will give us the same view controller as the last example. As discussed  earlier, lines 5 through 7 set properties of the view controller, this time changing properties to use a different image and text than the default values of the class. The code sets a yellow background as well.

Line 9 tells the system to present this modal as a popover. There are two ways to present a popover, one for popovers originating in toolbar buttons and one which presents a popover attached to a CGRect and displayed in some view. Both start the same. We set a modal presentation style of .popover, then present the popover like the modal view we did for the pizza.

The difference between popovers  on a CGRect and on a bar button is in the next two lines, which must come immediately after the presentation. These two lines of code set up the popover that anchors to a CGRect and presents itself in the space of a UIView. When we use a popover to present, we get a popoverPresentationController on the modal view. This controls the appearance and presentation of the popover. The property sourceView of popoverPresentationController indicates the view that the popover will appear, which often is view. The property sourceRect indicates the CGRect that the popover will be anchored to. In this example I attached the popover to the button that opens it, which is a common occurrence.

Now build and run. Select the popover button, and it works.

2016-06-30_06-05-06

Popovers often appear from bar button items in a toolbar or navigation bar. While we need two properties for a popover off of a CGRect, for a bar button item you need only one, appropriately named barButtonItem. Though we do not use it on our project, an equivalent code for using a bar button item might be this:

@IBAction func openPopover(sender:UIBarButtonItem){
    let vc = PopoverProgVC()
    vc.modalPresentationStyle = .Popover
    presentViewController(vc, animated: true, completion: nil)
    vc.popoverPresentationController?.barButtonItem = sender      
}

You can see an example of bar button items  in the lesson about UIImagePickerController. They look like this:

2016-06-28_08-14-44

Size Classes, Modals, and Popovers

Prior to iOS8, popovers and modals were different. Starting with iOS8, popovers became a type of modal. This was due to size classes. While I go into the details about size classes in my books Swift Swift View Controllers and Practical Autolayout, the basics of size classes is that your layout changes and adapts to different size screens and orientations automatically.

Before iOS8, if you ran a popover on any iPhone, you would get an error. Now iOS just adapts. For most phones in most orientations you get a .fullscreen modal presentation. Try it. Select an iPhone 6s in the simulator, and run the app again. Select a popover and you get a modal in portrait and landscape:

2016-06-30_06-11-402016-06-30_06-14-39

The iPhone 6 plus and 6s plus in landscape will give you a .formsheet presentation style for a popover, but  .fullscreen in Portrait. Try iPhone 6s plus in the simulator.

2016-06-30_06-17-28 2016-06-30_06-17-51

Starting with iOS9 on iPads, we also have mutitasking, which will act like an iPhone for popovers. Run the simulator With an iPad air 2. I rotated my screen for better effect by pressing Command-right arrow:

2016-06-30_06-21-06

With the simulator running, hit Command-Shift-H to get back to the home screen. Select Safari as an app. Drag from the right edge of the screen towards the center.

2016-06-30_06-23-59

In the icons that appear, pick the Swift3PizzaModal app, then once loaded, click the modal once again.

2016-06-30_06-31-36

On the left you will have Safari, on the right our App, though compressed. Try the popover again and you get a .fullscreen popover.

2016-06-30_06-24-22

Drag the white bar to the left of our app, and the bar turns black. Move it to the center. We still get a .fullScreen.

2016-06-30_06-24-49

Instead of having to figure out any of these cases, the adaptive layout features of iOS does it for you. For popovers, views with a compact width get a .fullsheet modal view and ones with a regular width get a popover or .formsheet.

We’ve covered the basics of popovers and modals. Modals work anywhere, on iPhone or iPad. Popovers and some special case modals work or appear differently on iPad only. In this lesson we saw how similar popovers are to modals. There is a few more things to do with modals which we will still need to get to. In future posts, we’ll discuss the one popover bug that will definitely get you kicked out of the app store, and how to avoid it.

The Whole Code

ViewController.swift

//
//  ViewController.swift
//  Swift3PizzaPopover
//
//  Created by Steven Lipton on 6/29/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//
// Demo of various ways or presenting modal view controllers

import UIKit

class ViewController: UIViewController {

//
//Programmatic ways of presenting modals
//the goal is to get a view controller and 
// present it with present(vc, animated: true, completion: nil)
//
// for a storyboard identifier, we use  
//    let vc =  (storyboard?.instantiateViewController(
            withIdentifier: "Pizza"))!
//for a view controller with programmatic layout we use 
//    let vc = init()
//

    @IBAction func openPizzaProgModal(_ sender: UIButton) {
       /* //using a story board
        let vc = (storyboard?.instantiateViewController(
            withIdentifier: "Pizza"))!
        vc.view.backgroundColor = UIColor.orange
        vc.modalTransitionStyle = .crossDissolve
        present(vc, animated: true, completion: nil)
       */
        
        //using a view controller
        let vc = PizzaModalProgViewController()
        vc.modalTransitionStyle = .partialCurl
        present(vc, animated: true, completion: nil)
    }
//
// To present a modal from its segue identifier use  this
//    performSegue(withIdentifier:String, sender: self)

    @IBAction func openPizzaModal(_ sender: UIButton) {
        performSegue(withIdentifier: "Pizza", sender: self)
    }
//
// Presenting popovers
// Popovers are a special presentation style of a modal view controller
// which present a small window on iPads, and a  full screen modal on other devices
// From a segue, you present it the same way as any other modal 
// From a view controller, you need two more components
//
// 1) set the modalPresentationStyle property to .popover 
//    vc.modalPresentationStyle = .popover
// 2) Tell the popover where to present. This code goes immediately after the 
// present() call. If you are anchoring to a view, you need two lines of code    
//        vc.popoverPresentationController?.sourceView = viewToPresentIn
//        vc.popoverPresentationController?.sourceRect = aCGRectToAnchorTo
//
//If anchoring to a UIBarButtonItem, you need only one line of code
//   vc.popoverPresentationController?.barButtonItem = aBarButtonItem
//
    @IBAction func openPopover(_ sender:UIButton){
    /* //Present a popover from a segue
        performSegue(withIdentifier:"Popover", sender: self)
    */
    //Present a popover programmatically
        let vc = PizzaModalProgViewController()
        vc.modalPresentationStyle = .popover
        //change properties of the view controller
        vc.text = "Cheesy!!"
        vc.imageName = "popover_sm"
        vc.view.backgroundColor = UIColor.yellow
        //present from a view and rect
        present(vc, animated: true, completion: nil)
        vc.popoverPresentationController?.sourceView = view
        vc.popoverPresentationController?.sourceRect = sender.frame
        /*
         //Code to present popover from a bar button Item,
          //though we don't have one in this example.
         present(vc, animated: true, completion: nil)
         vc.popoverPresentationController?.barButtonItem = sender
        */
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

PizzaModalViewController.swift

//
//  PizzaModalViewController.swift
//  Swift3PizzaPopover
//
//  Created by Steven Lipton on 6/29/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit

class PizzaModalViewController: UIViewController {


//
// Dismissal code for any modal 
//
    @IBAction func pizzaModalDone(_ sender: UIButton) {
        dismiss(animated: true, completion: nil)
    }

}

PopoverViewController.swift

//
//  PopoverViewController.swift
//  Swift3PizzaPopover
//
//  Created by Steven Lipton on 6/29/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit

class PopoverViewController: UIViewController {

//
// Dismissal code for any modal 
//
// Note on popovers this is not necessary, since any touch outside the popover
// dismisses the popover. However, if presented as a full sheet on a compact width device, 
// this is necessary. For code to hide the done button based on traits, 
// see  my book Swift Swift View Controllers

    @IBAction func popoverDone(_ sender: UIButton) {
        dismiss(animated: true, completion: nil)
    }
}

PizzaModalProgViewController.swift

//
//  PizzaModalProgViewController.swift
//  Swift3PizzaPopover
//
//  Created by Steven Lipton on 6/29/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//
//  Code to programmatically create a View Controller. 
//  Explanation of this code is beyond the scope of this lesson
//
//
import UIKit

class PizzaModalProgViewController: UIViewController {
    let dismissButton:UIButton! = UIButton(type:.custom)
    var imageName = "pizza_sm"
    var text = "BBQ Chicken Pizza!!!!"
    
    let myLabel = UILabel()
    
    func pizzaDidFinish(){
        dismiss(animated: true, completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Build a programmatic view
        
        //Set the Background color of the view.
        view.backgroundColor = UIColor(
            red: 0.8,
            green: 0.6,
            blue: 0.3,
            alpha: 1.0)
        // Add the image to the view
            let myImage:UIImage! = UIImage(named: imageName)
            let myImageView = UIImageView(image: myImage)
            myImageView.frame = view.frame
            myImageView.frame = CGRect(
                x: 10,
                y: 10,
                width: 200,
                height: 200)
            view.addSubview(myImageView)
        // Add the label to the view
        myLabel.text = text
        myLabel.frame = CGRect(
            x: 220,
            y: 10,
            width: 300,
            height: 150)
        myLabel.font = UIFont(
            name: "Helvetica",
            size: 24)
        myLabel.textAlignment = .left
        view.addSubview(myLabel)
        
    //Add the Done button to the view.
        let normal = UIControlState(rawValue: 0) //UIControlState.normal doesn't exist in beta(#27105189). This is a workaround.
        dismissButton.setTitle("Done", for: normal)
        dismissButton.setTitleColor(UIColor.white, for: normal)
        dismissButton.backgroundColor = UIColor.blue
        dismissButton.titleLabel!.font = UIFont(
            name: "Helvetica",
            size: 24)
        dismissButton.titleLabel?.textAlignment = .left
        dismissButton.frame = CGRect(
            x:10,
            y:275,
            width:400,
            height:50)
        dismissButton.addTarget(self,action: #selector(self.pizzaDidFinish),for: .touchUpInside)
        view.addSubview(dismissButton)
    }

}

How to Use UIImagePickerController for a Camera and Photo Library in Swift 3.0.

2016-06-28_08-20-54

Almost every iPhone and iPad now has a camera. Many people want to use a camera in their apps for various reasons. While you may not be building the next Instagram or Twitter, there are many places where photo documentation comes in handy.

There are two ways to use the camera. The more powerful and advanced method is using AVFoundation, but it is also a very complicated way to get a photo out of the camera.

The simpler way is the UIImagePicker. This is a quick way as Swift has simplified much of the code for it.  It is also the best way to fetch photos from the photo album. In this lesson, we’ll set up a basic camera and library app. In upcoming posts we’ll add a few embellishments to it that will make for a more effective camera.

Set Up The Layout

We’ll be talking about some of the issues with camera on both iPad and iPhone, so we’ll make this a universal app.  We will be using a dab of auto layout as well. If you want a brief introduction to auto layout go over and take a look at my book Practial Autolayout. You won’t need it for this lesson, but it may make what I do a little more understandable.

Make a new project SwiftPizzaCam with a single view and using Swift. As already mentioned, make the device Universal.

If you are not familiar with Xcode 8’s interface builder bar and the auto layout icons, here is a guide to help you as we go through setting up the app.

2016-06-28_05-29-33

Click on the iPhone 6s class preview. A new selection of previews appears.

2016-06-28_05-39-43

Select the iPad 9.7″ device.  then zoom out to 50%

2016-06-28_05-55-24

Xcode 8 come with a series of easily accessible preview modes in interface builder.  We will put a photo into an UIImageView when we first  use the image, and doing so on an iPad is easier than an iPhone, though it will work on both.  Right-click and save the image below:

pizza

Click on Assets.Xcassets and drag the pizza file into the assets folder. Go back to the story board and select the clip icon.  You will find the pizza media there.

2016-06-28_05-49-14

Drag out the pizza to the view and drop it into the view controller.

2016-06-28_05-58-42

Click the pin pinMenuButtonbutton.  Click off Constrain to Margins. Click on all the I-beams, then set their value to 0 points  like the image below:

2016-06-28_06-01-52

Be sure to press tab after you type in any number in this popover. It has an annoying habit of forgetting them if you don’t. Select Update Frames: Items of New Constraints towards the bottom.  Click  Add 4 Constraints. In the properties change the View Mode to AspectFit to properly size the photo.

Screenshot 2014-12-03 08.48.32

Now drag out a label to the storyboard. Set the background property to a Light Gray( #AAAAAA) color with a 65% alphaCenter Align the label text with a 28 point font size. Change the text of the label to read Pizza Cam!!!.  Select the label,  and then  click the pin button pinMenuButton. Set the top  8 points,  left and right sides 0 points, but not the bottom, like this:

2016-06-28_06-24-32

Make  sure you select Update Frames: Items of New Constraints towards the bottom before clicking  Add 3 Constraints.

Drag out  a toolbar and place toward the bottom of the view. Using the pin menu pinMenuButton, Pin it to the bottom, left and right like this, again updating the frames:

2016-06-28_06-21-16

Add a bar button item and a flexible space bar item to the toolbar. In one of the two bar buttons label it Photo and the other Library. Your tool bar and layout should look like this:

2016-06-28_06-26-34

 

Select the iPhone 6s in the preview modes. It should look like this:

2016-06-28_06-27-22

If you did everything correctly, you should have no auto layout warnings. If you do, go to the resolver and click Update Frames on the bottom half of the menu that appears.  If things get messier after doing this, clear the constraints on the bottom of the resolver, and pin everything again.

Wire Up the Outlets

Your next step is to wire up all the outlets and actions. Open the assistant editor.  Control-drag from the pizza photo  image and make an outlet called myImageView. Control drag from the Library button and make an action called photoFromLibrary with a sender of type UIBarButtonItem. This is important for stuff we will do later. Do this again, but with the Photo button and named shootPhoto. Again, make the sender UIBarButtonItem.
You can clean up the code a bit if you like. When done you should have something like this:

import UIKit

class ViewController: UIViewController{
    @IBOutlet weak var myImageView: UIImageView!

    @IBAction func shootPhoto(_ sender: UIBarButtonItem){
}
    @IBAction func photofromLibrary(_ sender: UIBarButtonItem) {
   }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }
}

Add the UIImagePickerController and Delegate

The star of our show the UIImagePickerController is missing. We do that programmatically. Close the assistant editor, and open ViewController.swift. Add the following line under the outlet for myImageView:

let picker = UIImagePickerController()

The UIImagePicker does much of its works from a delegate. Add the following to the class description:

class ViewController: UIViewController, 
    UIImagePickerControllerDelegate,
    UINavigationControllerDelegate {

We actually have two delegates: UIImagePickerControllerDelegate and UINavigationControllerDelegate. The UINavigationControllerDelegate is required but we do nothing with it. In the viewDidLoad, add the following:

 override func viewDidLoad() {
        super.viewDidLoad()
        picker.delegate = self
    }

We have wired up the delegate. Unlike other delegates, there is no required methods. However, this will not work without implementing two methods. At the bottom of the class, add the following:

//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController,
    didFinishPickingMediaWithInfo info: [String : AnyObject])
{
        
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        
}

These two methods handle our selections in the library and camera. We can either handle the cancel case with imagePickerControllerDidCancel or handle media with didFinishPickingMediaWithInfo

Getting a Photo from the Library

The UIImagePickerController is a view controller that gets presented modally. When we select or cancel the picker, it runs the delegate, where we handle the case and dismiss the modal. Let’s implement the photo library first, then the delegates. Add the following code to the photoFromLibrary method:

@IBAction func photoFromLibrary(_ sender: UIBarButtonItem) {
   picker.allowsEditing = false
   picker.sourceType = .photoLibrary
   picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
   present(picker, animated: true, completion: nil)
}

To get to the photo picker, it is three lines of code. We already initialized picker. In line two, we tell the picker we want a whole picture, not an edited version. In line three, we set the source type to the photo library. Line four we set the media types for all types in the photo library. Line five calls present to present the picker in a default full screen modal.

If you build and run, you could press the photoFromLibrary method, but then get stuck in the library. We need delegates to get out of the library. First let’s add the code for the imagePickerDidCancel delegate method:

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
       dismiss(animated: true, completion: nil)
    }

This does nothing special: it dismisses the modal controller. If we do pick a photo, we want to do something with the photo. Add the following code to the didFinishPickingMediaWithInfo delegate method:

func imagePickerController(_ picker: UIImagePickerController,
    didFinishPickingMediaWithInfo info: [String : AnyObject])
{
    let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage //2
    myImageView.contentMode = .scaleAspectFit //3
    myImageView.image = chosenImage //4
    dismiss(animated:true, completion: nil) //5
}

One of the parameters of this method is info. It has a dictionary of various information about the selected media, including metadata,  a user edited image if the .allowsEditing property is true, and a NSURL location of the image. For our camera app, the important key is the UIImagePickerControllerOriginalImage. We take that key and put the image into a variable. We could make this a constant, but there is some future iterations of this project that will need this as a variable.

Camera images are usually bigger than a UIImageView on a device. To shrink them quickly to a visible size, the best way is to set the .contentView property of our UIImageView to .ScaleAspectFit as we do in line 3.

Security for the Photo Library

Run in the simulator as an iPhone 6s. You should get a screen like this:

2016-06-28_07-07-54

Tap the Library bar button. The app crashes:

2016-06-28_07-08-30

In the simulator, there’s no message about what happened, the system just ends the application. Apple requires any use of the camera, the photo library or any personal information for that matter asks the user to agree sharing information with the app on the first use. For the UIImagePicker, this is included in your first run of the app.  Starting with iOS10, there’s another layer of security on the photo library. The developer must make an entry in the info.plist describing why they want to use the photo. That description will show up in an alert when the user decides to allow access to the library.

There’s two ways to add this entry: in XML or in the property list. We’ll use the property list first.  In Xcode,  select Info.plist from the Navigator pane

2016-06-28_07-21-27

Right click on the Information Property List Row. In the menu that appears, select Add Row.

2016-06-28_07-22-27

You get a new row with a drop down menu. Select Privacy – Photo Library Usage… from the menu.

2016-06-28_07-28-07

With the row still highlighted, click the value column  and add why you want access to the photo library.  In this app we are setting a background image.

2016-06-28_07-31-16

If you wish to add this directly to XML, the key/value is this

<key>NSPhotoLibraryUsageDescription</key>
<string>Set the Background</string>

We’ll come back to this for the camera, and do it in XML.

Build and Run again. Click the Library button, and you will get the permissions alert with the description we placed in the property list:

2016-06-28_07-33-57

Tap OK.  We get our Image picker,

2016-06-28_07-41-08     2016-06-28_07-41-29

When we tap a photo, it appears on the app.

2016-06-28_08-00-41

Running as an iPhone and iPad app: Using Popovers

Stop the app and run as an iPad 2. After answering OK to the library privacy question you get this:

2016-06-28_08-04-30

Which looks fine, except Apple doesn’t like it. They want you to use a  popover. Popovers must access the photo library on iPads.   Fortunately, it is very easy to get the popover to work. Add the highlighted lines in photoFromLibrary

    @IBAction func photoFromLibrary(_ sender: UIBarButtonItem) {
        picker.allowsEditing = false
        picker.sourceType = .photoLibrary
        picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
        picker.modalPresentationStyle = .popover
        present(picker, animated: true, completion: nil)
        picker.popoverPresentationController?.barButtonItem = sender
    }  

Line 5 selects a presentation style of a popover. We then present the popover. Line 7 sets the reference point for the popover to the bar button item. As I mentioned in another post popovers need a reference rectangle to pop up from. In this case, we can use the UIBarButtonItem which happens to be sender . This is why it was so important to use UIBarButtonItem as the sender type.

Build and run with the iPad 2 simulator. Now we have a popover to pick a photo.

2016-06-28_08-14-44

 

Since present checks the class size, you will get the proper behavior on any phone .The iPhone 6s Plus in the simulator does this.

2016-06-28_08-20-16 2016-06-28_08-20-54

 

We save ourselves from hours of device fragmentation work this way.

Adding a Camera

Basic Camera code is almost the same as adding a photo library. Change the shootPhoto code to this:

@IBAction func shootPhoto(_ sender: UIBarButtonItem) {
    picker.allowsEditing = false
    picker.sourceType = UIImagePickerControllerSourceType.camera
    picker.cameraCaptureMode = .photo
    picker.modalPresentationStyle = .fullScreen
    present(picker,animated: true,completion: nil)
}

We changed the sourceType property to .camera and specified the cameraCaptureMode property to .photo. The camera, unlike the photo library, is required to be full screen, so we don’t make it a popover, but explicitly a .FullScreen.

Like the library, we have another info.plist entry to make. This time we’ll use XML. Right click the info.plist and in the menus select Open As> Source Code:

2016-06-28_08-48-01

Just below the tag <dict>add this:

<key>NSCameraUsageDescription</key>
<string>Set the background of the app with your beautiful photography</string>

We’re ready to run. However, if you build and run this in the simulator, you will crash. In order to test and use camera code you have to use a real connected device. I connected my iPad Pro and ran the code. When I pressed the photo button, I again get the message about allowing access.

IMG_0379

Tapping OK, I get the camera:

IMG_0381

Take a picture, and the app asks me if I want to keep it.

IMG_0382

The app returns with my photo.

IMG_0383

Preventing the Camera Crash

This all works, but we really want to prevent that crash if there is no camera. Add the highlighted lines to shootPhoto:

 @IBAction func shootPhoto(_ sender: UIBarButtonItem) {
    if UIImagePickerController.isSourceTypeAvailable(.camera) {
        picker.allowsEditing = false
        picker.sourceType = UIImagePickerControllerSourceType.camera
        picker.cameraCaptureMode = .photo
        picker.modalPresentationStyle = .fullScreen
        present(picker,animated: true,completion: nil)
    } else {
        noCamera()
    }
}

Line 2 uses the class method isSourceTypeAvailable to checks if we have a camera. If there is, run the camera. If not explain to the user the device does has noCamera. For that function, we’ll add an alert like this, using UIAlertController:

func noCamera(){
        let alertVC = UIAlertController(
            title: "No Camera",
            message: "Sorry, this device has no camera",
            preferredStyle: .alert)
        let okAction = UIAlertAction(
            title: "OK",
            style:.default,
            handler: nil)
        alertVC.addAction(okAction)
        present(
            alertVC,
            animated: true,
            completion: nil)
    }

Line 2 makes an alert with the proper message. We add an OK action button on lines 6 through 10, then present the alert as a modal in line 11 onwards. With this code, if you run in the simulator, you get this when you attempt to take a picture:

2016-06-28_09-29-39

The Basics, but Wait! There’s more!

Basic UIImagePickerController is relatively easy to implement, but there are a lot of issues it leaves hanging:

  • Hitting no for privacy settings for  accessing the camera or library
  • Dealing with more than one popover
  • Customizing and adding more controls for the camera
  • Adding and playing video
  • Using  and storing pictures
  • Using a UIScrollView to zoom and scroll around a picture.
  • Getting rid of  the memory warnings
  • Wanting more power over my camera controls
  • Sharing pictures with my friends

Many of these could be questions that can be answered in context with the camera app, or outside of that context. In other lessons I’ll be answering them both ways.

The Whole Code

//
//  ViewController.swift
//  SwiftPizzaCam
//
//  Created by Steven Lipton on 6/28/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit

class ViewController: UIViewController,
    UIImagePickerControllerDelegate,
    UINavigationControllerDelegate
{
    let picker = UIImagePickerController()
    @IBOutlet weak var myImageView: UIImageView!
    
    @IBAction func photoFromLibrary(_ sender: UIBarButtonItem) {
        picker.allowsEditing = false
        picker.sourceType = .photoLibrary
        picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
        picker.modalPresentationStyle = .popover
        present(picker, animated: true, completion: nil)
        picker.popoverPresentationController?.barButtonItem = sender
    }
    
    @IBAction func shootPhoto(_ sender: UIBarButtonItem) {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            picker.allowsEditing = false
            picker.sourceType = UIImagePickerControllerSourceType.camera
            picker.cameraCaptureMode = .photo
            picker.modalPresentationStyle = .fullScreen
            present(picker,animated: true,completion: nil)
        } else {
            noCamera()
        }
    }
    func noCamera(){
        let alertVC = UIAlertController(
            title: "No Camera",
            message: "Sorry, this device has no camera",
            preferredStyle: .alert)
        let okAction = UIAlertAction(
            title: "OK",
            style:.default,
            handler: nil)
        alertVC.addAction(okAction)
        present(
            alertVC,
            animated: true,
            completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        picker.delegate = self
    }

    //MARK: - Delegates
    func imagePickerController(_ picker: UIImagePickerController,
        didFinishPickingMediaWithInfo info: [String : AnyObject])
    {
        var  chosenImage = UIImage()
        chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage //2
        myImageView.contentMode = .scaleAspectFit //3
        myImageView.image = chosenImage //4
        dismiss(animated:true, completion: nil) //5
    }
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
       dismiss(animated: true, completion: nil)
    }

}

Using Segues and Delegates for Navigation Controllers in Swift 3.0

It should be one of the easiest things we do, and yet for many it is the most confusing. Getting data from one view controller to another as you switch views never seems easy. Segues might be slightly difficult, but delegates to get the information back have given many a developer a headache or two. In this lesson, we’ll discuss this often used technique. This lesson will make a new small app which is nothing but a segue, a delegate, and a few controls to prove they work.

Make a New App

The First Scene

Make a new single-view Swift project named DelegateExample. In the storyboard click on the view controller, and embed it in a navigation controller by selecting Editor>Embed In> Navigation Controller.

2016-06-27_05-19-05

Press Command-N to make a new file.  Select a Cocoa Touch Class for the file and name the file FooOneViewController with UIViewController as a subclass:

2016-06-27_05-27-35

Go back to the storyboard, select the view controller and change the class to FooOneViewController in the identity inspector

Add a label in the center of the view, centered and with the text Unknown Color. Drag a bar button item to the right side of the navigation bar. Change its title to Color. It should look something like this.

2016-06-27_05-36-13

Open the assistant editor. In the view controller, remove everything but the viewDidLoad() method. Control-drag  connect an outlet for the Unknown Color label called colorLabel. Your code should look like this:

class FooOneViewController: UIViewController {

    @IBOutlet weak var colorLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

The Second Scene

Like our first controller, Press Command-N and make a new Cocoa Touch class that subclasses UIViewController. Call it FooTwoViewController. In the code, remove everything but the viewDidLoad() method.

Go back to the storyboard and drag in another view controller. From the Foo One Navigation bar, control-drag the Color Bar button item to the new controller to connect the segue. Set the segue to show.

2016-06-27_05-44-53

In the attributes inspector set the identifier to mySegue.

2016-06-27_05-47-23

Select the new view controller again in the storyboard. Once we’ve set the segue, in the identity inspector set the custom class for this view controller to be FooTwoViewController like we did the first class

Now we’ll add a label, a navigation item, a bar button item, and three buttons. First add the label and place it towards the center of the view. Make the label the width of the view. Place the three buttons under the label. Title the buttons Red, Green and Blue respectively. Drag a navigation item into the view and in the label, title it Foo Two. Finally add the bar button item to the navigation bar. Your finished view should look like this:

2016-06-27_05-53-43

Open the assistant editor if not already open. Control-drag the label into the FooTwoViewController class. Create an outlet named colorLabel. Select the bar button, and control-drag it to the class code.  Make an action named saveColor.

2016-06-27_05-57-36

Select the Red, Green and Blue buttons, and control drag them into FooTwoViewController. Make an action for a UIButton called colorSelectionButton.

2016-06-27_05-59-48

In the colorSelectionButton method add this code:

@IBAction func colorSelectionButton(_ sender: UIButton) {
        colorLabel.text = sender.titleLabel!.text!
    }

Above the colorLabel outlet add a string variable colorString:

var colorString = "I don't know the color"

Finally, add this to viewDidLoad() to set the label correctly from the property:

colorLabel.text = colorString

Your code for FooTwoViewController should look like this:

import UIKit
class FooTwoViewController: UIViewController {
    var colorString = "I don't know the color"
    @IBOutlet weak var colorLabel: UILabel!
    @IBAction func saveColor(_ sender: UIBarButtonItem) {
    }
    @IBAction func colorSelectionButton(_ sender: UIButton) {
        colorLabel.text = sender.titleLabel!.text!
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        colorLabel.text = colorString
    }
  }

Build and Run. Tap the color button, and make sure in Foo Two you can tap the red, green and blue buttons and see the color name in the label. If you can’t stop the simulator and go to the assistant editor. Place your mouse cursor over the plus in front of the color selection button. The three buttons should highlight like this:

2016-06-27_06-09-49

If they don’t highlight the button did not get connected. Drag from that plus to a unhighlighted button to connect it.

Adding prepare for segue

To move data from Foo One to Foo Two, we will override prepare(for segue:). If you have the assistant editor open, close it.  Go into the FooOneViewController.Swift file and under the viewDidLoad method but before the end of the class, type prepare. Xcode will show you choices in the drop down menu

2016-06-27_06-19-48

Click the selection for prepare( for segue:  on the drop down.  You’ll have this:

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
        code
    }

Add the following code to this method so the prepare(for Segue: ) reads:

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "mySegue"{
        let vc = segue.destinationViewController as! FooTwoViewController
        vc.colorString = colorLabel.text!
    }
}

In line 1, the first parameter is segue, which is a UIStoryboardSegue object. This is the segue we call for our transition between controllers. In line 2 we check to see if this is the correct segue. This is line of code where a lot of bugs happen. Be sure that the string you are comparing matches exactly the segue identifier set in the storyboard, otherwise the code won’t do anything. Line 3 we create vc which is the pointer to the segue’s destination view controller. destinationViewController is of type AnyObject!. Swift will only assume vc is a type UIViewController, not our specific instance of it. We need to downcast to the correct object type with the as! operator, and make vc an instance of FooTwoController. Once we do that, we can access the colorString property in line 4, sending our current text to the property in the new controller.

Build and Run. We now can send “Unknown Color” to the new controller.

2016-06-27_06-32-38

Now comes the slightly more challenging part: getting stuff back. For that we will need a delegate.

Protocols and Delegates in Swift

Delegation uses protocols. Protocols are a set of  properties and methods that while declared in one place, another class implements. They allow for a layer of abstraction. A class adopts a protocol to do something. The protocol defines what the something is.  The adopting class will have the code how it gets done.  Using delegates and protocols is one of the hardest concepts for most developers to understand. For details about how this all works, I suggest reading the lesson Why Do We Need Delegates?

We are going to set up a protocol to dismiss the Foo Two controller, and then adopt it in the main view controller. This way we can indirectly access properties of the Foo Two controller. Such an access is a delegate. In the Foo Two controller above the class definition for FooTwoViewController, add the following:

protocol FooTwoViewControllerDelegate{
    func myVCDidFinish(controller:FooTwoViewController,text:String)
}

This sets up the protocol FooTwoViewControllerDelegate with a required method myVCDidFinish(). I used an incredibly generic name here, you can of course make it more specific for readability. Next, in the FooTwoViewController class, add the following just after the class definition:

var delegate:FooTwoViewControllerDelegate? = nil

We define a delegate of optional type FooTwoViewControllerDelegate and set its value to nil. We are familiar with simple values such as a Double or Int. If we want a state for any object that has a nil state, we use an optional value. Declare an optional with a question mark after the type, as it is above. An optional value of a Double? can be nil, along with any number for example. There is a cost to this extra power. To get back that number you have to unwrap the optional value. You can use the ! or ? operator to return a value as long as the optional is non-nil. If nil, it will break program execution with a run-time error.
unexpectedly found nil while unwrapping an Optional value
Before unwrapping an optional value, it’s usually a good idea to check for nil. There are several ways of doing that. For example, we could write the saveColor method like this:

    @IBAction func saveColor(sender : UIBarButtonItem) {
        if (delegate != nil) {
            delegate!.myVCDidFinish(self, text: colorLabel!.text!)
        }
    }

This will prevent run-time errors. However there are situations where run time errors are telling you exactly what’s wrong in your application. For delegates, I often don’t check delegate for nil. If I get the nil error message, I know I didn’t set the delegate right.

@IBAction func saveColor(sender : UIBarButtonItem) {
            delegate?.myVCDidFinish(self, text: colorLabel!.text!)
 }

There is one other way to handle this situation, and that is to use the guard keyword to unwrap your optional. Add this one to our code.

@IBAction func saveColor(_ sender: UIBarButtonItem) {
    guard let delegate = self.delegate else {
        print("Delegate for FooTwoDelegateController not Set")
        return
    }
    delegate.myVCDidFinish(controller: self, text: colorLabel.text!)
}

Guard creates a new local constant called delegate that isn’t optional. If nil it runs code to print to the console we didn’t set the delegate. If not we run the myVCDidFinish method, sending to this function colorLabel.text!. As a protocol, it isn’t defined here. The adopting class defines it, so our next stop is adopting the protocol back at the original view controller.

Open the FooOneViewController.swift file. Change the class definition to:

class FooOneViewController: UIViewController,FooTwoViewControllerDelegate

You should immediately get this error:
Type ViewController does not conform to protocol FooTwoViewControllerDelegate
We need to write the protocol. On a blank line just above prepare(for segue: ), add this code:

func myVCDidFinish(controller: FooTwoViewController, text: String) {
    colorLabel.text = "The Color is " +  text
    controller.navigationController?.popViewController(animated: true)
}

This is the sneaky part. The arguments go the function are values from FooTwoViewController, but the function is in FooOneViewController. We take the value of text and place it in our label. We then use the controller to dismiss the controller with popViewControllerAnimated.(beta note: I’m getting a warning on this, but it works. I’m assuming a bug here)

Build and run. Tap Color, then Green then Save. On the Console you’ll get an error message:
Delegate for FooTwoDelegateController not Set

This is the most common error with delegates(and why I prefer a fatal error to a soft notification on the console). We need to set up the delegate in the segue. Change the prepare(for segue:), adding the highlighted line

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "mySegue"{
            let vc = segue.destinationViewController as! FooTwoViewController
            vc.colorString = colorLabel.text!
            vc.delegate = self
        }
    }

Build and run. You should be able to send “unknown” to Foo Two. Click a color and send the color back.

2016-06-27_07-34-17

The Steps to a Delegate

Here’s a summary of this steps to setting up delegation in Navigation controllers

  1. Between two view controllers, set up a segue with a segue identifier
  2. In the source view controller, set up the prepare( for segue:) to send the destination any values necessary. Test this works.
  3. Add a protocol to the destination view controller with a method declaration.
  4. Make the protocol and optional value named delegate in the destination controller.
  5. When you are ready to dismiss the controller and send back values, call the delegate method.
  6. Adopt the protocol in the source view controller
  7. Add the required delegate method to the source view controller
  8. Add to prepare( for segue:) the statement vc.delegate=self

If you are not understanding what we did here, you might need a little help with a few background concepts of delegation, MVC and encapsulation. This is the how, not why. For the why,  read Why Do We Need Delegates

The Whole Code

FooOneViewController.swift

//
//  FooOneViewController.swift
//  DelegateExample
//
//  Created by Steven Lipton on 6/27/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit

class FooOneViewController: UIViewController,FooTwoViewControllerDelegate {

    @IBOutlet weak var colorLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func myVCDidFinish(controller: FooTwoViewController, text: String) {
        colorLabel.text = "The Color is " +  text
        controller.navigationController?.popViewController(animated: true)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "mySegue"{
            let vc = segue.destinationViewController as! FooTwoViewController
            vc.colorString = colorLabel.text!
            vc.delegate = self
        }
    }

}

FooTwoViewController.swift

//
//  FooTwoViewController.swift
//  DelegateExample
//
//  Created by Steven Lipton on 6/27/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit
protocol FooTwoViewControllerDelegate{
    func myVCDidFinish(controller:FooTwoViewController,text:String)
}

class FooTwoViewController: UIViewController {
    var colorString = "I don't know the color"
    var delegate:FooTwoViewControllerDelegate? = nil
    @IBOutlet weak var colorLabel: UILabel!
    @IBAction func saveColor(_ sender: UIBarButtonItem) {
        guard let delegate = self.delegate else {
            print("Delegate for FooTwoDelegateController not Set")
            return
        }
        delegate.myVCDidFinish(controller: self, text: colorLabel.text!)
    }
    @IBAction func colorSelectionButton(_ sender: UIButton) {
        colorLabel.text = sender.titleLabel!.text!
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        colorLabel.text = colorString
    }
  }

How to Debug Programs and Life

For several reasons related to WWDC2016, I’m breaking up the sequence I’m doing on XML. We’ll continue that next week, but this week I’m giving you the article I wrote from this week’s Slice Of App Pie podcast on debugging. I’ve had several questions on the issue. this is the first of several responses. Look for this fall a whole series on Debugging.

If you’d like to hear me talk about debugging, listen to the podcast here or click here for the episode web page.

Let me tell you two stories. The first is a story about Rear Admiral Grace Hopper. She was one of the first people to program what we think of as a modern computer, and wrote the first compiler, and the Language COBOL. On September 9, 1947, there was an error in the computation on the Harvard Mark II computer she was working with. Some of the staff found a moth had gotten caught in a relay, causing the error. She taped the moth to her notes for the day.


By Courtesy of the Naval Surface Warfare Center, Dahlgren, VA., 1988. – U.S. Naval Historical Center Online Library Photograph NH 96566-KN, Public Domain, https://commons.wikimedia.org/w/index.php?curid=165211
While a moth is not a bug, and others used the term before her, for years afterwards she would tell this story, and is credited with popularizing the term  bug first in the computer industry, and eventually the world.

My second story is one I get often. Over on my MakeAppPie.com website, the most frequent communication I get is “your code doesn’t work.” I go and look at the code, and find it does. What I rarely get is, “I was having problems with your code, and found that on line 6 of the function printSomething in class ViewController needs to be  let a:[String:AnyObject]! = nil not a:[String:String]! = nil.

The difference between those two comment is the second case debugged the code. The first did not. Over at MakeAppPie.com it does happen that Apple switches versions of Swift or an API on me, and the code fails. But the first commenter did not bother to look, or even bother to get specific about why it didn’t work. The second did some work.

Not enough people do that work from what I can tell.From the questions I ask them after that first comment, I think they don’t know how to. Not enough people learn about debugging. I’d like to do some explaining about debugging.

I find there are two kinds of bugs:my bugs and not my bugs. My bugs are the things that I did wrong. I like these bugs. I have control over them. If I can do something wrong, I can fix it. I have control of the situation.

There are three bugs that I can do something about: syntax errors, logical Errors and Design Errors. Syntax errors are bugs where I typed code wrong. For example in JavaScript I could have this function:

function myFunction(p1, p2) {
var p = p1 * p2
return p;
}

Because I forgot a semicolon after the calculation of p1*p2, I have a syntax error and the application will not run. One of the most frustrating things about JavavScript is it won’t tell you when there is a syntax error. Fortunately most languages are a lot more explicit about syntax errors. If you did this in Swift

func whatIsX(x:Int!) {
if x = nil {
print(“No Value for X”)
}
var result = String(format”X is %i”,x)
Print (result)
}

Xcode would light up in errors and warnings.  From the IBM Sandbox (you can try this here: http://swiftlang.ng.bluemix.net/#/repl/575eaa89d4c6c057192c0ba4) I got this:
ERROR at line 9, col 27: expected ‘,’ separator
var result = String(format”X is %i”,x)
^
,
ERROR at line 6, col 10: cannot assign to value: ‘x’ is a ‘let’ constant
if x = nil {
~ ^
ERROR at line 9, col 21: use of unresolved identifier ‘format’
var result = String(format”X is %i”,x)
^~~~~~
ERROR at line 10, col 1: use of unresolved identifier ‘Print’
Print (result)
^~~~~

Sometimes syntax errors are hard to understand. The first error says I’m trying to assign a constant with nil, wich I can’t do. You sometime have to do a little interpreting. I want to compare x and nil. I used the assignment operator = when I should have used a comparison operator  != or ==.  I also forgot a : after format to make it a parameter. Swift is case sensitive and Print should be print. If I changed my code to this I’d get rid of the errors..almost: IBM sandbox

func whatIsX(x:Int!) {
if x != nil {
print(“No Value for X”)
}
var result = String(format:”X is %i”,x)
print (result)
}

I get one more warning to change var to let.

/swift-execution/Sources/main.swift:6:9: warning: variable 'result' was never mutated; consider changing to 'let' constant
    var result = String(format:"X is %i",x)
    ~~~ ^
    let

So I change it to this:
func whatIsX(x:Int!) {
if x != nil {
print(“No Value for X”)
}
let result = String(format:”X is %i”,x)
print (result)
}

And then I get no errors. (IBM Sandbox)

Syntax errors of the fatal kind like x=nil don’t get too far. Your program will not compile. Warnings like changing var to let, will let the program work, but often they might cause problems later on as the second kind of bug, a logical bug.

Logical bugs will give you wrong answers or wrong functionality. Since  most compilers catch all the syntax errors, this is the most common like of bug. The program can run but it doesn’t do what we want. In the same function, there is no errors or warnings, but is has two bugs. If you called the function wahtIsX(x:nil) you’d crash with an unwrapping error.(IBM SandBox)

fatal error: unexpectedly found nil while unwrapping an Optional value

If you called whatIsX(x:5) you’d get(IBM Sandbox)

No Value for X
X is 5

We have two bugs. the first is the logical operator in the if statement. It should be equals  == instead of not equals !=.  Secondly,  we have a flow of execution problem. The if statement executes, then continues down the code. With X having a value of nil, it cannot unwrap that in the String function. There’s two solutions for this. We could use an else clause for the second print, or we can return after encountering a nil. I used the second

func whatIsX(x:Int!) {
if x == nil {
print(“No Value for X”)
return
}
let result = String(format:”X is %i”,x)
print (result)
}

Now we run with both function calls and the function works. (IBM Sandbox)
whatIsX(x:nil)

No Value for X

whatIsX(x:5)
X is 5

The third kind of error is a design error. I tend to break these into two categories, code design and user experience(UX) design. Let’s look at UX design first. Apple has an entire set of design guidelines (https://developer.apple.com/design/), including the Human interface guides and a webpage (https://developer.apple.com/design/tips/ )summarizing good design. Android does too. (https://developer.android.com/design/get-started/principles.html) If your user has a problem using your app, they wont use it. Let’s take one simple design principle that works with phones. Compare these two layouts:

One has the button on the top, one on the bottom. People hold their phones  one-handed so they can do most functions with their thumbs. Most thumbs don’t reach the top of the phone, while all reach the bottom. It’s better design to put a frequently pressed button on the bottom. If you want one that requires bit more effort, and possibly a bit of reflection, place it on the top.

There is serious research in this topic. The master on this topic is Donald Norman,who at one time worked for Apple on this subject.  His book the Design of everyday things is a classic in understanding Human Centered design. These design issues are found everywhere, not only user interfaces. For a simple example here’s a video of  Don Norman talking about doors

The other design error is code design. We can get rid of many logical bugs by designing them out. For example suppose you have a 1GB database based on a web server somewhere. You could load the entire database into you phone and then find the few record you want, but that is not good design. It takes up lots of memory, maybe enough to blow out the application. Instead you design the program to ask for only the records you need, not all the ones you don’t.

Code design bridges my bugs and not my bugs. The not my bugs category has  the errors that aren’t your fault. At best, you can assume they are going to happen in your application and design your application to deal with them. For example look at these two phones:

The one of the left is designed to constrain your answer to Yes or No. The one on the right might have yes, Yes, Yah, maybe, no, No, What, are you crazy, NO!!!!, or  a 5-paragraph essay on Don Norman’s design principles. Which is easier to code for and get expected results? Which would be near impossible to do any analysis on? That’s design at work.

Let go back to the web database for another example. I can’t assume anything about the data I’m getting from that server. It may give me the right data. It might give the wrong data, corrupted data, take forever for data to reach me, not make a connection with the server, or have a interrupted connection with the server. My design accounts for each of those possibilities, since any one of them might crash my app as a bug. This is where error handlers and validators come into design. Prevent the bug by adding code that deals with it happening.

The last bug that isn’t my fault is the one written by somebody else’s code. If you are reading this close to when I published it, there’s a perfect example you’re probably going to be battling. Consider this code, which is the WhatIsX function but adds one to x before printing:

func whatIsX(x:Int!) {
if x == nil {
print(“No Value for X”)
return
}
var y = x!
y++
let result = String(format:”X is %i”,y)
print (result)
}

That worked fine last week in Xcode(you might get a warning about the bug though), but if you use the IBM Sandbox and I’m guessing the new Xcode available after WWDC2016, things will not be so nice. Both  are Swift 3.0 implementations,  you’ll get this error:(IBM Sandbox)

ERROR at line 8, col 6: '++' is unavailable: it has been removed in Swift 3
    y++
     ^~
      += 1

Swift 3.0 has some syntax changes. Removing ++ or is one of them. You have to write this code with y +=1:
(IBM Sandbox)
func whatIsX(x:Int!) {
if x == nil {
print(“No Value for X”)
return
}
var y = x!
y += 1
let result = String(format:”X is %i”,y)
print (result)
}

Updates to the language, APIs or third party libraries are all subject to this kind of thing regularly. You have to fix syntax changes to the language and changes in implementations of APIs as they happen.  We’re stuck with the compiler, but this is one reason I minimize my use of 3rd party libraries. Some might think I reinvent the wheel, but I’m paranoid: how do I know it is a wheel?. How to I know this code is secure? The amount of testing and validation I have to do to prove it (and in medical devices It’s mandatory to do such testing)  means I might as well write and test my own code. .

Bugs mean the application doesn’t, work, doesn’t do what I want it to and it could do one more thing: It doesn’t do what I want in an acceptable way. Blowing out my memory by loading an entire data is an example. So is a memory leak, where something is gobbling storage and taking up a lot more memory than it should need.

So how do I find bugs? I test for them. Testing can become a complex thing, but I’ll go through a few of the most simple ways I look for and find bugs.  Testing means testing the entire application at different levels. It is testing individual methods to make sure they work. It is also testing the classes to make sure they work, and testing the whole application. It is testing the user interface by giving a copy to a few users and seeing what they think. For each of these I find the bugs, I find the failures in the code.

Finding them is sometimes easy, sometimes hard. Your two simplest tools for debugging is printing to the console and breakpoints. Printing to the console which we do with  print/write/NSLog depending on the language you are using gives us a value of a variable while the application runs. It can tell us two things: that the values for this variable are correct and that the application reached the point where the print is.

Sometimes I want to know that execution happened, but I don’t need to watch a value change. That’s where breakpoints are useful. With most development environments  that allow breakpoints you can also explore  the current values of all your variables and instances. Using those two I find most of the logical errors.

Other times you need stronger tools. Breakpoints and print statements don’t  work alone for memory leaks.  For those you’ll need some monitoring applications. Xcode of course includes Instruments, but other development environments have similar tools.

Once I know what’s wrong I fix it. Very often I’ll find it is a simple mistake. Sometimes it may need a more extensive change.

One I fix it, I I test again. And fix the bugs I might have introduced in the fix, until I’m happy I have no bugs.

This has been quite technical, but somewhere in that technical stuff is a lot you can take away that is about life and any situation. Let’s summarize the above with a few observations that true anywhere.
Be Sherlock Holmes – When problems or failures arise, don’t fret. Instead start the detective work to find out what is wrong. Dig and dig deep to find the problem. use whatever tools will help you find the causes. Most people hate problem solving. Be like Sherlock — seriously enjoy the hunt for the culprit.
Own your mistakes — You’ll often find you either caused the failure or contributed to the failure. Own the mistake. What you own you have control over. That means you fix it, and move forward. If you blame Apple for every bug you get, you will never get a finished product.  If you blame someone else for every problem you have  in life, you will be stuck doing nothing forever.
Laugh at your mistakes -While there are exceptions, most stuff is the small stuff, such as using plus instead of minus somewhere.  These knuckle-headed  mistakes deserves only one response: you laugh at your silliness, and then you fix it.
If it’s not your mistake, work around it the best way possible– Sometimes it is not your fault, and you have no control over the situation. There are always workarounds. Find a workaround to fix it. Get guidance about the workaround from other with the same problem. Sometime the ones at fault might give you a workaround.  If the situation changes and there is a more direct solution than your workaround, its a great idea to use the more direct solution. Workarounds and hacks have a bad habit of attracting bugs.
Design so there are no mistakes– Start your project with a clear vision of what your want. Find all the things you can that might cause problems before you make anything. Play with the system a bit to see if there are any bugs you missed. Only then plan out your design so you avoid as many of those bugs as possible.
Think like a user, not an engineer or artist: Donald Norman and Bruce Tognazzini , Another  former Apple exec who wrote the first Human Interface guide,  wrote a rather long post on how Apple lost its way on design. . While rather long and a very good read, the point is clear: Apple has stopped thinking about how people use their devices and instead spend too much time making it pretty. My book  Practical Auto Layout is of course my favorite example of one of Apples big mistakes. Apple describes an actually simple layout system as quadratic equations between views in stead of pinning and aligning views, losing all the developers in the process. Aple didn’t think of how most developers think. Think of your audience first. Immerse yourself in that audience. Find what they do and think like them. If you don’t, people won’t like your product and won’t use it, nor will they recommend it to their friends.
The always one more bug paradox. You cant get rid of every bug. Some bugs are bugs  because some of your users think one way and others another way. You can’t satisfy both. You can sit there getting pixel perfect and not shipping. This is Resistance doing its worst. Perfect is not the goal, getting a minimum viable product is. Get it working without any additions to your plan, or major revisions. If anyone is fails at this rule constantly at this it is me. I have to kick myself frequently to just get it done and ship. This lesson is an example. It was supposed to be a quick summary of a podcast and became a major article. I get stuck in a paradox. You want to wow your audience, but you also want to ship the minimum viable product. The only advice I can give (I’ll talk more about this in next weeks podcast) is get the product out, and do a lot of revisions after you do. Unless you are major-league recognized brand, a few mistakes will not kill you. Even for large brands a few mistakes didn’t kill them. Apple shipped Apple Maps before it was ready. At first it was a disaster, but it didn’t kill the company, and I like using MapKit far more then Google maps when I code map. Just fix your mistakes, apologize for the inconvenience, make it better and keep going.

There’s this emphasis on coding these days. That’s only a third of good programming. The other two thirds, design and debugging are as important. As life skills they may be more important. I hoped I’ve given those of you who haven’t thought too much about debugging some help and advice about how to think about those other two thirds.