Episode #139

Today Extensions in iOS 8

12 minutes
Published on October 2, 2014

This video is only available to subscribers. Get access to this video and 572 others.

One of iOS 8's more powerful new features is App Extensions. With extensions we have a whole new range of possibilities. In this episode we'll focus on the Today Extension, which is a way to add a widget to Notification Center for quick access.

Episode Links

Sharing Code Between App and Extension

You will likely want to share code between your app and extension. There are a couple of ways to approach this. One quick way is to just add the class to both targets. Another approach that offers more flexibility is to move shared code into a framework that is referenced by both the app and the extension.

Today Extension

Your extension is just a view controller, which offers familiar functionality and behavior. You are encouraged to use Auto Layout to layout your views, and use intrinsicContentSize to indicate to the system how tall your widget wants to be.

class TodayViewController: UIViewController, NCWidgetProviding {

    @IBOutlet var coffeeTracker: CoffeeTracker!

    override func viewDidLoad() {
        super.viewDidLoad()
        coffeeTracker.updateDisplay()
    }
}    

Here we've encapsulated our logic between our step counter and the views, as well as the storage into NSUserDefaults, as you can see here:

import UIKit

@objc class CoffeeTracker : NSObject  {
    @IBOutlet weak var numberLabel: UILabel!

    var numberOfCups: Int = 0 {
        didSet {
            updateDisplay()
        }
    }

    func updateDisplay() {
        numberLabel.text = String(numberOfCups)
    }

    @IBAction func stepperChanged(stepper: UIStepper) {
        numberOfCups = Int(stepper.value)
    }
}

The outlet and action are wired up in storyboards in each target.

Updating Content Periodically

Your widget may want to periodically update content so that when the user opens the Notification Center the content is already there. For this you must implement widgetPerformUpdateWithCompletionHandler:.

    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
        // Perform any setup necessary in order to update the view.

        // If an error is encountered, use NCUpdateResult.Failed
        // If there's no update required, use NCUpdateResult.NoData
        // If there's an update, use NCUpdateResult.NewData

        completionHandler(NCUpdateResult.NoData)
    }

Here you can perform any network or disk-based synchronization and update your interface accordingly. You must call the completion handler indicating if you had results or not (or if you encountered an error). Update the user interface as a result of your operation so the system can snapshot your views and provide a recent picture of the data to your users.

This episode uses Ios 8.0.