Tag Archives: Auto Layout

Where is Update Frames in Xcode 8.1?

A tech author’s work is never done. As soon as he or she completes manuscript and gets it published, the manuscript almost immediately becomes obsolete. In my case, Practical Autolayout for Xcode 8 went obsolete  a day before I published, but I had no idea about a major change in Xcode 8.1.

Until Xcode 8.1, if you wanted to update a frame with new constraints, you had two possibilities. The first was in the pinpinMenuButton and align alignment iconmenu to update as you were setting the constraints.

2016-11-29_06-05-32

The second was a selection in the resolver resolver button 2016-10-01_13-27-48

It seems everyone, including me was not ready for a change Apple made in Xcode 8.1. If you go to look for Update Frames in the resolver resolver button, it is missing:

2016-11-29_06-11-52

So where did it go?

Apple moved this to an icon on the auto layout toolbar and deleted it from the menus.

2016-11-28_07-29-22

If it were me, I wouldn’t have deleted it from the menus in such an abrupt way. Apple did. This Update Frame button  has some different behaviors  from its predecessor on the menu, and I’d like to explain that using some examples from Chapter 3 of Practical Autolayout for Xcode 8

Set up a storyboard that looks something like this with a label Hello Pizza, a text view, and  three  buttons, Pepperoni, Cheese, and Done:

2016-11-29_05-54-14

Select the Hello Pizza label.  Click the pin buttonpinMenuButton in the auto layout toolbar. In the popup, set the top to 0 points, the left to 0 points and the left to 0 points.  Leave Update Frames as None

2016-11-29_05-56-06

Add the 3 constraints. The Hello Pizza Label will show misplacement constraints.

2016-11-29_05-56-32

Press the Update Frames button update frames  and the frame updates.

2016-11-29_06-37-41

This is not always the result. You must have all constraints satisfied before the button will update frames. For example, select the text view. Press the align button alignment iconand center the text view by checking on Horizontally in Container and Vertically in Container.

2016-11-29_05-54-38

Again don’t update frames, but click  Add 2 constraints. You’ll see an ambiguous constraint in red.

2016-11-29_05-55-13

If you click the update frames button nothing happens. Until a frame has no ambiguity(i.e. no red constraint errors), you cannot update it. Most often that is setting a size. For the text box, set an absolute size in the pin menu pinMenuButton  of 175 points in both directions.

2016-11-29_05-57-41

Add the constraints. The errors all turn to misplacements.

 2016-11-29_05-58-39

Once all misplacements, you can update the frame with update frames.

2016-11-29_07-15-35

Priorities are not assumed with the new update frames button. When there is an ambiguity in size between two frames that depend on each other for size, you must specify the a priority for them or set a size.  Take for example these two buttons.

2016-11-29_05-45-35

Pepperoni is pinned to the left margin, the label above it and the text view below it. Cheese is pinned 10 points from Pepperoni, aligned to the top of Pepperoni, and pinned 10 points from the right margin. We’d like to have two buttons that fill the available space.

The option used in Practical Auto Layout for these buttons is to make them the same size. Control drag from Pepperoni to Cheese. A menu appears.

2016-11-29_06-56-57

Shift select Equal Width and Equal Heights, then hit the Add Constraints selection. The ambiguity changes to misplacements.

2016-11-29_06-57-14

Select both the Pepperoni and Cheese buttons. Hit the Update Frame button update frames and two equally sized buttons appear

2016-11-29_06-58-00

The other, more advanced option is to change priority of one of the buttons so they are not equal. Both are by default 250.  Going back to the original ambiguous layout,

2016-11-29_05-45-35

changing the content hugging priority of Pepperoni from 250 to 251 tells auto layout for Pepperoni to keep its size and Cheese to stretch to make up the difference.

2016-11-29_06-56-19

Priorities are covered in detail in Chapter 12 of Practical Autolayout for Xcode 8.

I’ll be updating the book shortly. Until then or if you cannot update your book,  consider this an errata to the versions now available.

practical-autolayout-x8-newsletterPurchase the book for  Kindle and iTunes  here:

get_it_on_ibooks_badge_us_1114

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 Add Stack Views Programmatically and (almost) avoid AutoLayout

Some people don’t like Interface Builder and like to code instead. Sometimes your layout is so dynamic you need to lay out in code. In either case, programmatic layout of views becomes the answer instead of auto layout. In Xcode 7 Apple introduced stack views. In an earlier post, I introduced stack views in Interface Builder. There are still some problems with stack views in Interface Builder, but those problems do not appear in code. In this lesson I’ll introduce how to use stack views in code.

The Theory

Stacks views are really simple: they are arrays of views with a few properties. You initialize the stackview with an array of views and set a few properties: axis, distribution, fill and spacing. At run time, the views create constraints the fulfill those requirements.

By doing this you can almost avoid auto layout with one exception: you need to use auto layout to layout the stack view on the superview. In our lesson, we’ll layout our stack view over the entire view and then  have a view that works with lots of embedded views and stack views.

Set up the Project

Create a new Universal project in Swift called StackViewCodeDemo. Since Xcode no longer marks the launchscreen, add a label to the launchscreen.storyboard with the title StackViewCodeDemo. I usually center this by clicking the align menu button and then center horizontally and vertically in the container and updating the constraints like this:

center alignment

Since the is programmatic, we need nothing on the storyboard.

The Button Generator

I’m going to use a series of buttons for my view objects. Go to the ViewController.swift code and add the following declarations to the class:

//MARK: Properties
let colorDictionary = [
    "Red":UIColor(
        red: 1.0,
        green: 0.0,
        blue: 0.0,
        alpha: 1.0),
    "Green":UIColor(
        red: 0.0,
        green: 1.0, 
        blue: 0.0, alpha: 1.0),
    "Blue":UIColor(
        red: 0.0,
        green: 0.0,
        blue: 1.0,
        alpha: 1.0),
]

This dictionary gives us a color name for a key and a UIColor for a value. Now add the follow function to the class:

//MARK: Instance methods
func colorButton(
     withColor color:UIColor,
     title:String) -> UIButton
{
   let newButton = UIButton(type: .System)
   newButton.backgroundColor = color
   newButton.setTitle(
       title,
       forState: .Normal)       
   newButton.setTitleColor(
       UIColor.whiteColor(),
       forState: .Normal)
   return newButton
}
 

I’m keeping this simple. I built a method to make a button quickly with certain properties set. I left off the action, but you can certainly put it in here. I did this so I can iterate through my dictionary and make buttons. Make another method with this code:

 func displayKeyboard(){
//generate an array of buttons
    var buttonArray = [UIButton]()
    for (myKey,myValue) in colorDictionary{
         buttonArray += [colorButton(
             withColor: myValue,
             title: myKey)
         ]
}

We have an array of buttons that take their color and title from the dictionary.

Making a Stack View

We are now ready to make a stack view and add it to the superview. I’ll make one that will have the three buttons next to each other. Under the displayKeyboard we just wrote, add the following:

let stackView = UIStackView(arrangedSubviews: buttonArray)
stackView.axis = .Horizontal
stackView.distribution = .FillEqually
stackView.alignment = .Fill
stackView.spacing = 5
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)

The arrangedSubviews parameter of the UIStackView initializer takes an array of UIView objects and makes a stack view from it. We set the properties for the stack view, and shut off the autoresizing mask. I used a .Fill distribution which will stretch the buttons vertically to take the entire view. The distribution property makes equal width buttons. I set the buttons 5 points away from each other.

This stack view needs autolayout, which is why it was critical to shut off the autoresizing mask. We’ll lay out the stack view to be the view with a margin. I pinned the view to the left and right margins which are 20 points from the left and right sides, and 30 points above and below the top and bottom of the superview. Add this to your code:

//autolayout the stack view - pin 30 up 20 left 20 right 30 down
        let viewsDictionary = ["stackView":stackView]
        let stackView_H = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|-20-[stackView]-20-|",  //horizontal constraint 20 points from left and right side
            options: NSLayoutFormatOptions(rawValue: 0),
            metrics: nil,
            views: viewsDictionary)
        let stackView_V = NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|-30-[stackView]-30-|", //vertical constraint 30 points from top and bottom 
            options: NSLayoutFormatOptions(rawValue:0),
            metrics: nil,
            views: viewsDictionary)
        view.addConstraints(stackView_H)
        view.addConstraints(stackView_V)

I’ll leave this code as-is. It works fine for a template to use the entire view for a stack View. If you want to know more about Auto layout in code, see my post on it.

Finally add the method to the viewDidLoad

 override func viewDidLoad() {
        super.viewDidLoad()
        displayKeyboard()
    
    }

Build and run. You will have three buttons:

2015-11-11_07-31-41

Rotate and the buttons automatically change size and shape.

2015-11-11_07-31-42

Nesting Stack Views

Once we have one stack view, we can also nest stack views. comment out the following code:

/*
let stackView = UIStackView(arrangedSubviews: buttonArray)
        stackView.axis = .Horizontal
        stackView.distribution = .FillEqually
        stackView.alignment = .Fill
        stackView.spacing = 5
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        */

Add underneath it the following code:

let subStackView = UIStackView(arrangedSubviews: buttonArray)
subStackView.axis = .Horizontal
subStackView.distribution = .FillEqually
subStackView.alignment = .Fill
subStackView.spacing = 5
//set up a label
let label = UILabel()
label.text = "Color Chooser"
label.textColor = UIColor.whiteColor()
label.backgroundColor = UIColor.blackColor()
label.textAlignment = .Center

let blackButton = colorButton(withColor: UIColor.blackColor(), title: "Black")

I made a stack view like our last stack view, a label with white text on a black background, and a black button. Under that code add this:

let stackView = UIStackView(arrangedSubviews: [label,subStackView,blackButton])
stackView.axis = .Vertical
stackView.distribution = .FillEqually
stackView.alignment = .Fill
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)

We make a vertical stack view with the three views we defined. The order of the array is left to right in horizontal and top to bottom in vertical. I kept the same distribution and alignment as our first example, but added 10 points between the vertical view. Since our auto layout constraints for stackView are already set, we are ready to build and run. Check the view in both portrait and landscape.

2015-11-11_07-49-21

2015-11-11_07-49-32

Without a lot of coding for layout, stack views can make some quick adaptive layouts with a minimal amount of auto layout. Apple’s documentation encourages using stack views for the easiest and most adaptive layout, making coding for devices from a iPhone to an AppleTV easy. I kept this simple. In a real app, you probably want to add actions and have your views defined outside the displayKeyboard method as properties. You might want to play around with that and with changing the properties of the stack view to see the variation you can get with a stack view.

The Whole Code

//
//  ViewController.swift
//  StackViewCodeDemo
//
//  Created by Steven Lipton on 11/11/15.
//  Copyright © 2015 MakeAppPie.Com. All rights reserved.
//

import UIKit



class ViewController: UIViewController {
    //MARK: Properties
   
    let colorDictionary = [
        "Red":UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0),
        "Green":UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0),
        "Blue":UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0),
    ]
    
    //MARK: Instance methods
    func colorButton(withColor color:UIColor, title:String) -> UIButton{
        let newButton = UIButton(type: .System)
        newButton.backgroundColor = color
        newButton.setTitle(title, forState: .Normal)
        newButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
        return newButton
    }
    
    
    func displayKeyboard(){
                 //generate an array
       
        
        var buttonArray = [UIButton]()
        for (myKey,myValue) in colorDictionary{
            buttonArray += [colorButton(withColor: myValue, title: myKey)]
        }
        /* //Iteration one - singel stack view
        let stackView = UIStackView(arrangedSubviews: buttonArray)
        stackView.axis = .Horizontal
        stackView.distribution = .FillEqually
        stackView.alignment = .Fill
        stackView.spacing = 5
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        */
        
        //Iteration two - nested stack views
        //set up the stack view
        let subStackView = UIStackView(arrangedSubviews: buttonArray)
        subStackView.axis = .Horizontal
        subStackView.distribution = .FillEqually
        subStackView.alignment = .Fill
        subStackView.spacing = 5
        //set up a label
        let label = UILabel()
        label.text = "Color Chooser"
        label.textColor = UIColor.whiteColor()
        label.backgroundColor = UIColor.blackColor()
        label.textAlignment = .Center
        
        let blackButton = colorButton(withColor: UIColor.blackColor(), title: "Black")
        
        let stackView = UIStackView(arrangedSubviews: [label,subStackView,blackButton])
        stackView.axis = .Vertical
        stackView.distribution = .FillEqually
        stackView.alignment = .Fill
        stackView.spacing = 10
        stackView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(stackView)
    
        //autolayout the stack view - pin 30 up 20 left 20 right 30 down
        let viewsDictionary = ["stackView":stackView]
        let stackView_H = NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[stackView]-20-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
        let stackView_V = NSLayoutConstraint.constraintsWithVisualFormat("V:|-30-[stackView]-30-|", options: NSLayoutFormatOptions(rawValue:0), metrics: nil, views: viewsDictionary)
        view.addConstraints(stackView_H)
        view.addConstraints(stackView_V)
    }
    //MARK: Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        displayKeyboard()
    
    }



}


Why Stack Views Are Your Best Friend If You Hate Auto Layout

If you hate auto layout, you may be surprised to learn Apple does too. In Xcode 7 Apple introduced a new way to work with constraints called stack views. Stacks are containers that keep views aligned automatically. Originally announced as a lazy man’s auto layout, you do need to understand auto layout to use it correctly. For this demo and introduction to stack views, we’ll make an options page for dessert pies. We’ll suppose we will use this as a modal view, so we need to add our own navigation.

Horizontal Stack Views

Create a new project and go to the storyboard. Add a label titled Pie Options. Add two buttons titled Cancel and Done. Place them toward the top of the scene like this:

image221

Select all three items. Click the stack button in the Auto layout menu buttons.

stackButton

It has no menu, but there will be a change in the storyboard. Your three views now are embedded in a horizontal stack view.

image222

Stack views can be pinned like any other view. Pin the stack view 0 points up, 0 Points Left and 0 points right, with update set to Items of new constraints

image223

Besides the odd placement of the items in the stack view, the labels and buttons are not aligned. In the attributes menu for the stack view, Select First Baseline for Alignment and Fill Equally for Distribution.

image224

Our stack view rearranges to have equal width for all the subviews, and the text in the labels and buttons align to the baseline.

Image225

However the Label is still left justified. Select the label and center justify it.

image226

Our pseudo toolbar is now complete, a lot faster than pinning the three views

Vertical Stack Views

Add a label Topping and four buttons Whipped cream,Chocolate Sauce,Caramel Sauce and None. Give the buttons a blue background with white text. Arrange them vertically like this:

image227

Select the label and buttons, then click the stack view button. Stack views know you want a horizontal or vertical view by context. This gets a vertical stack view.

image228

Stack view also take by context what type of Alignment and distribution they’ll use. Due to the centered labels, the stack view centered the buttons. Change the Alignment to Fill. Also change the spacing to 3.

image229

This makes equal width buttons and a 3 point space between them.

image230

Pin the new stack view 10 points up, 0 points left and 0 points right. Update the frame. Checking in the assistant editor’s preview mode, we see that both landscape and portrait adapts to the new layout.

image232

In the preview and storyboard, you’ll see a background to the stack view. In an app, a stack view always has a background of clearColor. Don’t waste your time, trying to change the background.

That’s the basics of Stack views. In my upcoming book Practical Autolayout for Xcode 7, we’ll cover more about stack views including  embedding them, and some of the perils of stack views.

Practical Auto Layout: Are You Ready for iOS 9?

Practical Autolayout Cover 3Apple messed up big time. They wanted a simple, powerful but flexible system to lay out buttons, labels, images and other objects on the storyboard. They wanted a way to make only one layout and have it work on any iOS device in any orientation. They created Auto Layout and Size classes. Then they messed up. They didn’t tell anyone how to easily use it. Developer’s have been skirting around Auto Layout for years, confused by bizarre menus and strange icons. Instead, many developers spend weeks writing extra code for the iPhone app or a landscape mode. Developers can lose thousands of potential customers by making a iPhone or iPad only app.

This might be you.

In iOS8 Apple required popovers, modal views, Alerts and Split views to use size classes. In iOS9, multitasking requires it. But most developers do not know the difference between a regular width and compact width. Doing so, they risk their code becoming obsolete and useless.

If you’ve ever used presentViewController:, this may be you.

In Practical Auto Layout, using simple, practical, easy to follow examples, you will learn how to master auto layout and size classes on the storyboard. Using easy to follow examples, you will learn how to make universal apps quickly easily and in far less time than ever before. You’ll learn how to use constraints the right way, how to avoid and resolve errors such as misplacements and conflicting constraints. You be able to customize your layout for both launch screens and your application, using buttons, labels, images, text fields and more.

With a quarter century of technical training experience, Author Steven Lipton will teach beginners to expert developers in Practical Auto Layout how to use this immensely useful tool to make amazing applications for more devices in half the time.

Available on

 

6 Themes to Expect at Apple’s WWDC 2015 No One is Talking About.

Once a year, Apple developers get together in San Francisco. Some lucky people in person, most through on-line connections. The event is the World Wide Developer’s Confrence (WWDC), the event for those people and companies developing applications for OSX and iOS. As a developer, I look froward to this event every year and have a different take than most commentators.

Apple has a calendar of releases. In June at WWDC, Apple gives the developers enough warning to get their applications and skills up to speed for the fall hardware releases. Generally, late September announces the new Hardware with a October or November release date. There are notable exceptions like the Apple Watch which had several announcements and a release date only weeks before WWDC2015.

Some members of the press figured out that when Apple warns developers about something,  it must mean some big news at Apple. Everyone now shows up to write some headline about Apple. Apple never tells the whole story at WWDC. Often hardware related programming gets held back even from developers.

Like a good television series there are story arcs and trends that follow Apple products. Very often these trends at WWDC get missed.

 The Press Getting it Wrong

This is an annual tradition, and of course the press would never admit they goofed big time, along the lines as the Apple watch will never amount to anything and Google Glass is the way to go.  Most, if not all, of the press are not programmers of any kind, let alone work with Xcode regularly. They invariably miss the big stuff going on to concentrate  over some shiny new toy that’s relatively meaningless in the scheme of things, which might be the Spotify competitor this year.

You can expect post-keynote for the press to be generally disappointed and exclaiming this the decline of Apple for lack of innovation this year, missing what really happened. It’s not completely their fault of course. They write for consumers, and what goes on under the hood doesn’t concern them.

The Big Theme: High Quality, Good Style Fast to Market

Apple’s strategy for the last few years has been towards rapid development of applications by developers.  All of the points  following this one depend on this overarching idea. Build fast enough that rapid hardware changes can be adapted to quickly, and any new hardware has a large amount of apps on release day.  Rapid development also means it’s an easy environment to get into for beginners. The ease of development makes many a developer stay with the one platform.

The Game Development System

Over the last few years Apple has built a robust game development environment into Xcode and iOS.   Two years ago  there was SpriteKit. Last year there was Metal for 3D rendering. Most of these tools are still code-based. I’d expect if this arc continues to see a full game engine or at least several new tools for non-code creation of games.

Apple is rumored to give developers more access to what the Apple watch does. One that might affect the gaming side is gesture based games. Use of the motion sensors on the watch to control your game would open up a lot of gaming experiences.

The Apple Watch and HealthKit/ResearchKit

This is the one I’m watching with the most interest. Apple now has a sophisticated fitness monitor sitting on people’s wrists with the Apple Watch.  As I said in gaming, the rumor mill is indicating that Watchkit will gain a lot more power to work with an Apple  watch than its paltry experience now.

All that data filters through Healthkit now but those Watchkit changes might open up the heart rate monitor and motion sensor to developers. I’d bet on the motion data more than the heart monitor, but both are possible.  Apple introduced ResearchKit in the same press conference as  Apple Watch. To borrow a phrase from Marvel Comics,  it’s all related.

If Apple can find ways around two sets of regulations, Apple Watch and HealthKit will disrupt healthcare like they have credit cards and music. On one level, people will have a lot of personal data to make health decisions from — some not like any other fitness monitor out there.

As an owner of an Apple Watch, and Fitbit Zip , Apple’s definition of exercise intrigues me. Just walking around is not enough.  My Fitbit said I had 19,732 steps for  9.17 miles of walking in 147 active minutes last Sunday.  Apple Watch’s activity app said I had 19,295 steps, for 9.77mi but only 20 minutes of exercise. Experimenting with this, Apple’s definition requires an elevated heart rate and faster walking pace  to count as exercise.  Why the difference?

Apple has repeatedly said the heart rate monitor is a measure of fitness – not a medical device. The reason is simple: to get FDA approval as a medical device is very costly and very complicated at this point for them. Apple at least now is dodging FDA and other international device regulations by claiming it’s not a medical device. Apple also has to deal with the hippo in the room: HIPAA. The security and privacy of patient data presents lots of problems for any mobile device or wearable. That said, if you come up with acceptable legal methods for sharing patient data, you could do some very interesting things. One that would benefit everyone is large-scale research into heath problems very inexpensively.  That’s what ResearchKit is about. Research would like that data. There are strong agreements within ResearchKit apps to release data. If those hold legally in this environment then there is one more environment they might work well in: insurance.

Insurance must work on aggregate data and a single snapshot of a person’s health. Short of a peek at one vitals at  a physical and doctor’s visits, there is no way insurance companies can estimate your health and fitness. If they had a years worth of near-continuous heart rate and exercise data they would have a better estimate of health. The more factors that actuaries have available the more realistic their measurement would be.

A healthy person is less likely to have conditions that would lead to expensive procedures.  It’s been pretty impossible to give a good economic incentive to healthy people or for people to become healthy.  The HealthKit/WatchKit arc might have as its disruptive end game that incentive. People who are healthy pay less for health insurance because they are less at risk. The Apple Watch’s stringent exercise requirements make sense in this light – you really do have to move to have exercise be called exercise.

Think about it: want to cut your insurance if you east healthy and exercose? Buy an Apple watch. Even the steep price tag of a phone and watch sells a lot of phones and watches on that savings.

Swift for Education

When Apple introduced Swift last year, they declared it a both a rapid development language and a educational language.  While developer based Swift is  everywhere, and developers new and old are reportedly preferring it over Objective-C, the education part is still missing. Apple introduced for Swift playgrounds for test coding and exploring of language features without developing a full application.

Xcode, even with playgrounds, is not a good place to introduce a fifth-grader to coding. A simpler environment is necessary and one that runs on hardware less expensive than a Macintosh.

I said it last year after the introduction of Swift: there needs to be a Playground app on iPad.  If made correctly, it could even scratch Scratch from early education.

If young or beginning coders learn Swift first, they re more likely  to stay with Swift and skip Android’s Java.

The Large Class size

One introduction that a lot of people missed at WWDC2014, including me, was the introduction of size classesand the impact on iOS.  I missed the reason they were necessary:the release of the iPhone 6 plus a few months later. Apple changed everything in the user interface code to accommodate size classes.  Size classes categorize the height and width of any device.  The system decodes how to layout the interface for that device – both for code and the graphically layout by designers and developers. Unlike earlier version of iOS, designers only have to design and develop code for User interfaces once — not five or six times.

in iOS8 there are two sizes: compact and regular. In general, Compact relates to iPhones and Regular relates to iPads.  Notice what’s missing:  Large.  An omission like that cannot be intentional. That’s implies there will be devices larger than an iPad.

While they may not announce any devices at WWDC2015, watch for any announcement of a large class size. A large tablet  (or improbably an complete OSX/iOS merger) will not be far behind.

I may be wrong, but this is what I will be watching for at the WWDC2015 keynote.

Swift Swift: How to Make a Drop Shadow in User Interfaces

2015-05-18_07-50-06

Flat User interfaces are a lie. They are not completely flat. One effect continues to be used with them to show depth: Shadows. In flat interfaces it can look like there are some views floating above others by the use of shadows. In this lesson we’ll learn to make shadows using the CALayer found in UIViews, and use them to make some special effects on UIButtons.

Make a new single-view project named SwiftShadowDemo with a Swift as the Language and Universal device. Go to the storyboard.  Drag a button on to the storyboard. Give it a Blue color for a background and white lettering.  Title it Shadow.

2015-05-15_07-28-32

With the button selected, Control-Drag Up from the button and to the left, until your cursor is on the white of the background scene. Release the button. You will get a menu. Shift select the items  Center Horizontally to Container, Center vertically to Container, Equal Widths and Equal Heights like this:

2015-05-15_07-31-29

You’ve probably not set the button in the exact center of the scene.  Go to the the size inspector and find the constraints. Select Edit on the  Align X to Shadow constraint. Change the constant to 0 .

2015-05-15_07-34-46

Do the same for the Align Center Y to Shadow. When done both constraints should read like this

2015-05-15_07-35-28

Now edit the Equal Width to Superview. Change the multiplier to 3 or 1:3 depending which gives you a smaller rectangle.

 2015-05-15_07-36-09

Do the same to Equal Height to Superview, with a multiplier of 3 or 1:3.  Next in the resolver menu, Update the frames

2015-05-15_07-37-16

This should give you a centered proportionally sized button:

2015-05-15_07-37-51

Open the assistant editor. Control-drag from the button to the code. Make an outlet named shadowButton.


 @IBOutlet weak var shadowButton: UIButton!

 

Control drag again from the button to the code. Make a action named shadowButton.

@IBAction func shadowButton(sender: AnyObject) {
}

Making Shadows on the CALayer

All UIViews have a special property layer of type CALayer. This is a Core Animation layer. As it name implies various animation effects to your views happen here.  The layer property is great for many quick special effects, some built-in. Drop shadows are one of those built-in effects.  Add the following to viewDidLoad.

shadowButton.layer.shadowOpacity = 0.7

The property shadowOpacity defaults to 0.  The shadow is always there, but hidden. To show a shadow, change the opacity. Build and run. We have a shadow:

2015-05-17_06-42-06

This shadow’s light source is from the lower right. Most times it’s best to have a light source from the top and left, so the shadow shows on the lower right. We change that by the  property of CALayer. Add this to viewDidLoad:

shadowButton.layer.shadowOffset = CGSize(width: 10.0, height: 10.0)

Build and run and you get this:

2015-05-17_06-52-19

We have  a nice bold shadow.  Usually shadows are subtle. Change the shadowOffset to this:

shadowButton.layer.shadowOffset = CGSize(width: 3.0, height: 2.0)

Build and run. The shadow is more subtle:

2015-05-17_12-18-32

We can also change the radius of the shadow. This affects how blurry the shadow appears.  Add this to viewDidLoad

shadowButton.layer.shadowRadius = 5.0

Build and run:

2015-05-17_12-25-10

We have a more blurred shadow.  We can also change the color of the shadow.  The default color is black. Let’s change the color to yellow.  Add this:

shadowButton.layer.shadowColor = UIColor.yellowColor().CGColor

Build and run. Rhe shadow now look like more of a glow.

2015-05-18_05-36-45

Glows are more radiant from the center. For a good glow effect change the code to the following:

shadowButton.layer.shadowOpacity = 0.7
shadowButton.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
shadowButton.layer.shadowRadius = 15.0
shadowButton.layer.shadowColor = UIColor.yellowColor().CGColor
view.backgroundColor = UIColor.grayColor()

To better see the glow we made the background gray to contrast against the glow.  Build and run:

2015-05-18_06-11-03

We get a glow behind the button.

While this is nice for a static shadow, glows and shadows make for dynamic effects on a button.  To the shadow button action, add the following code:

 @IBAction func shadowButton(sender: AnyObject) {
     shadowButton.layer.shadowOpacity = 0.7
     shadowButton.layer.shadowOffset = CGSize(width: 3.0, height: 2.0)
     shadowButton.layer.shadowRadius = 5.0
     shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
}

This will make our simple drop shadow when we release the button. When we press the button, we will give one of two shadow effects, depending on the selection on a segmented control.  Add this outlet and action to your code:

 @IBOutlet weak var touchDownType: UISegmentedControl!
@IBAction func shadowButtonTouchDown (sender: AnyObject) {
// code to change the button on pressing
    if touchDownType.selectedSegmentIndex == 0{ //make the button glow
         shadowButton.layer.shadowOpacity = 0.5
         shadowButton.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
         shadowButton.layer.shadowColor = UIColor.yellowColor().CGColor
         shadowButton.layer.shadowRadius = 20.0
    } else { //make the button depress by having a shadow in the upper left
         shadowButton.layer.shadowOpacity = 0.9
         shadowButton.layer.shadowOffset = CGSize(width: -3.0, height: -2.0)
         shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
         shadowButton.layer.shadowRadius = 2.0
    }
}

Go to the storyboard. Add a segmented control above the button. Control drag directly down from the segmented control to the button. In the auto layout menu that appears, Shift-select Vertical Spacing, Center X,  and Equal Widths

2015-05-18_06-28-31

As we did earlier with the button, we will change some constraints. With the segmented control selected, go to the size inspector.  Change the Bottom Space to Shadow  constraint to 20. Change Align Center X to Shadow to 0. Your constraints should read like this:

2015-05-19_05-33-50

Change the first segment title to Glow. Change the second segment title to Depression. Select the button. In the size inspector, change the Proportional width to Superview’s Multiplier to 1.5 if set it at 3. Set the multiplier to  1:1.5 if set at 1:3.

2015-05-18_06-38-29

Your scene should look like this:

2015-05-18_06-39-41

Open the assistant editor. From the circle next to the touchDownType outlet, drag to the storyboard to connect it to the segment.

2015-05-18_06-55-09

For events other than a touch up for a button we need to explicitly set the event. For our new action, we need to set an event for touching down on the button. Right click the button in the storyboard. In the menu that appears, find Touch Down. Drag from the circle to the right up to anywhere in the shadowButtonTouchDown  method’s code in the assistant editor. When the code highlights, release the button.

2015-05-18_06-59-05

We have wired our storyboard up. Now to set our default. Change viewDidLoad to this:

override func viewDidLoad() {
super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    shadowButton.layer.shadowOpacity = 0.5
    shadowButton.layer.shadowOffset = CGSize(width: 3.0, height: 2.0)
    shadowButton.layer.shadowRadius = 5.0
    shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
    shadowButton.setTitleColor(UIColor.yellowColor(), forState: .Highlighted) //need to show button title
    view.backgroundColor = UIColor(red: 0.25, green: 0.2, blue: 0.6, alpha: 1.0)
}

We set up our basic shadow, like we did in the touch up event. We also added two lines of code to makes things a bit more visible. First we changed the color of the button’s title. If we leave it as the white from the storyboard, it will disappear. Changing the color to yellow fixes this. Secondly, we gave a contrasting color to both our glow and shadow so they are visible.

Build and run. Rotate the device in the simulator with Command-Right arrow. You should see this:

   2015-05-18_07-21-47

Press the button, and the button should glow:

2015-05-18_07-22-14

Switch to Depression

2015-05-18_07-23-04

Press the button and the button seems to press down:

2015-05-18_07-23-28

This is some of the basics of drop shadows. You can do this to any UIView based control.  For example you can do this to the segment and a label, which we’ll leave to the reader to set up to produce the image below:


//a shadow on the segmented control and on a label
//label layout and setup is left to the reader.
let offset = CGSize(width: 3.0, height: 2.0) //keep offsets consistent -- usually make this a constant.
touchDownType.layer.shadowOpacity = 0.7
touchDownType.layer.shadowOffset =  offset
shadowLabel.layer.shadowOffset = offset
shadowLabel.layer.shadowOpacity = 0.9
shadowLabel.layer.shadowRadius = 7.0

2015-05-18_07-50-06

The Whole Code

//
//  ViewController.swift
//  SwiftShadowDemo
//
//  Created by Steven Lipton on 5/15/15.
//  Copyright (c) 2015 MakeAppPie.Com. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
//MAARK: - Outlets
    @IBOutlet weak var shadowLabel: UILabel!
    @IBOutlet weak var shadowButton: UIButton!
    @IBOutlet weak var touchDownType: UISegmentedControl!
//MARK: - Actions
    @IBAction func shadowButtonTouchDown (sender: AnyObject) { //When button is pressed down
        if touchDownType.selectedSegmentIndex == 0{
            shadowButton.layer.shadowOpacity = 0.5
            shadowButton.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
            shadowButton.layer.shadowColor = UIColor.yellowColor().CGColor
            shadowButton.layer.shadowRadius = 20.0
        } else {
            shadowButton.layer.shadowOpacity = 0.9
            shadowButton.layer.shadowOffset = CGSize(width: -3.0, height: -2.0)
            shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
            shadowButton.layer.shadowRadius = 2.0
        }
    }

    @IBAction func shadowButton(sender: AnyObject) { //When button released
        shadowButton.layer.shadowOpacity = 0.5
        shadowButton.layer.shadowOffset = CGSize(width: 3.0, height: 2.0)
        shadowButton.layer.shadowRadius = 5.0
        shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
    }
//MARK: - Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        shadowButton.layer.shadowOpacity = 0.5
        shadowButton.layer.shadowOffset = CGSize(width: 3.0, height: 2.0)
        shadowButton.layer.shadowRadius = 5.0
        shadowButton.layer.shadowColor = UIColor.blackColor().CGColor
        shadowButton.setTitleColor(UIColor.yellowColor(), forState: .Highlighted) //need to show button title
        view.backgroundColor = UIColor(red: 0.25, green: 0.2, blue: 0.6, alpha: 1.0)

        //extra code not in post - a shadow on the segmented control and on a label
        let offset = CGSize(width: 3.0, height: 2.0) //keep offsets consistent -- usually make this a constant.

        touchDownType.layer.shadowOpacity = 0.7
        touchDownType.layer.shadowOffset =  offset
        shadowLabel.layer.shadowOffset = offset
        shadowLabel.layer.shadowOpacity = 0.9
        shadowLabel.layer.shadowRadius = 7.0

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}