iOS Life

  • Home
  • ABOUT
  • SERVICES
  • PORTFOLIO
  • BLOG
  • Contact

Tutorial: Today Widget in Swift

App extensions in the Today view are called widgets. Widgets give users quick access to information that’s important right now. For example, users open the Today view to check current stock prices or weather conditions, see today’s schedule, or perform a quick task such as marking an item as done. Users tend to open the Today view frequently, and they expect the information they’re interested in to be instantly available.

The best widgets give users quick updates or enable very simple tasks. If you want to create an app extension that enables a multistep task or helps users perform a lengthy task, such as uploading or downloading content, the Today extension point is not the right choice.

Because user interaction with Today widgets is quick and limited, you should design a simple, streamlined UI that highlights the information users are interested in. In general, it’s a good idea to limit the number of interactive items in a widget. In particular, note that iOS widgets don’t support keyboard entry.

Below is a tutorial that implements a Time Widget to display clocks for a couple of time zones. This fits into the Apple requirement of making it a simple dynamic task that users may need frequently without wanting to open a full app.

Setup the Application Extension

  1. Select File > New > Project. Select the Single view application template, and call it TodayWidget.
    Screen Shot 2014-10-16 at 8.48.32 AM

  2. Add the Application Extension Target. Select File > New > Target…. Then in the left pane, select Application extension and under that choose Today Extension. Because our Today extension is going to show times, give it the name TimeWidget.
    Screen Shot 2014-10-16 at 8.50.37 AM

  3. A message will popup asking if you want to activate the “TimeWidget” scheme. Click Cancel. We will debug it using the normal Application scheme.
    Screen Shot 2014-10-16 at 8.51.37 AM

Create the Today Widget View

Today widgets are just like any other view within your application and built using a UIViewController. Next we’ll create our view for what will appear in the widget.

  1. In the project navigator, expand TimeWidget group and click on MainInterface.storyboard.
  2. Select the “Hello World” label already there and delete it.
  3. Click on the “View” and open the Size Inspector and change the height of the view to 60.
  4. Drag a eight UILabels into the view, the top four be the titles of the time zones and the bottom four will be clocks. See the image below.
    Screen Shot 2014-10-16 at 9.11.53 AM

  5. Define your IBOutlet label variables within the “TodayViewController.swift” and add in the perferredContentSize of the view so it will display the correct height in the Today View.
    //
    //  TodayViewController.swift
    //  TimeWidget
    //
    //  Created by Brian Coleman on 2014-10-16.
    //  Copyright (c) 2014 Brian Coleman. All rights reserved.
    //
    
    import UIKit
    import NotificationCenter
    
    class TodayViewController: UIViewController, NCWidgetProviding {
        
        @IBOutlet var pacificLabel: UILabel!
        @IBOutlet var mountainLabel: UILabel!
        @IBOutlet var centralLabel: UILabel!
        @IBOutlet var easternLabel: UILabel!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view from its nib.
            self.preferredContentSize = CGSizeMake(320, 50);
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
        
        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.NewData)
        }
        
    }
    
  6. Connect the IBOutlets to the new variables within the MainInterface.storyboard.
    Screen Shot 2014-10-16 at 9.21.06 AM

Test Your Today Widget

  1. When you run the app you’ll see a blank view since our app doesn’t do anything except create the Today Widget.
    Screen Shot 2014-10-20 at 12.45.13 PM

  2. Drag from the top of your view down to display the notification center. Next tap the “Edit” button.
    Screen Shot 2014-10-16 at 9.24.59 AM

  3. Tap the green plus button next to the TimeWidget. You’ll see it got added below the Calendar. Drag it to re-order it so it shows above the Calendar.
    Screen Shot 2014-10-16 at 9.25.05 AM

  4. Tap “Done” and you should see our TimeWidget displayed in the Today Widget view.
    Screen Shot 2014-10-16 at 9.25.23 AM

Add in Live Dynamic Data

We are almost done making our widget, let’s add in the clocks to finish it up.

import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {
    
    @IBOutlet var pacificLabel: UILabel!
    @IBOutlet var mountainLabel: UILabel!
    @IBOutlet var centralLabel: UILabel!
    @IBOutlet var easternLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view from its nib.
        self.preferredContentSize = CGSizeMake(320, 50);
        self.updateClocks()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    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.NewData)
    }
    
    func updateClocks() {
        var time: NSDate = NSDate()
        println("Time: \(time)")
        
        var timeString : NSString = "Time: \(time)"
        
        let formatter:NSDateFormatter = NSDateFormatter();
        var timeZone = NSTimeZone(name: "UTC")
        formatter.timeZone = timeZone
        formatter.dateFormat = "HH:mm"
        println("UTC Time: \(formatter.stringFromDate(time))")
        
        timeZone = NSTimeZone(name: "US/Eastern")
        formatter.timeZone = timeZone
        formatter.dateFormat = "HH:mm"
        println("EST Time: \(formatter.stringFromDate(time))")
        easternLabel.text = formatter.stringFromDate(time)
        
        timeZone = NSTimeZone(name: "US/Pacific")
        formatter.timeZone = timeZone
        formatter.dateFormat = "HH:mm"
        println("PST Time: \(formatter.stringFromDate(time))")
        pacificLabel.text = formatter.stringFromDate(time)
        
        timeZone = NSTimeZone(name: "US/Mountain")
        formatter.timeZone = timeZone
        formatter.dateFormat = "HH:mm"
        println("MT Time: \(formatter.stringFromDate(time))")
        mountainLabel.text = formatter.stringFromDate(time)
        
        timeZone = NSTimeZone(name: "US/Central")
        formatter.timeZone = timeZone
        formatter.dateFormat = "HH:mm"
        centralLabel.text = formatter.stringFromDate(time)
    }
}

You can grab the full source code for this tutorial. Note: Built for Xcode 6.0.

This is what your time widget should look like.
Screen Shot 2014-10-20 at 12.35.26 PM

Oct 20, 2014 Brian Coleman
TestFlight vs Enterprise DistributionTutorial: Share on Twitter and Facebook in Swift
You Might Also Like
 
Tutorial: Facebook Login in Swift using a Bridging Header
 
Tutorial: Building an Apple Watch Glance
8 years ago Swift, Tutorialsios8, swift, tutorial9,165
Follow Me
    
Categories
  • About Me
  • Frameworks
  • My Apps
  • News
  • Strategy
  • Swift
  • Tools
  • Tutorials
  • tvOS
  • Uncategorized
  • Videos
  • Watch
Archives
  • May 2016
  • January 2016
  • October 2015
  • July 2015
  • May 2015
  • April 2015
  • March 2015
  • November 2014
  • October 2014
  • September 2014
  • July 2014
  • June 2014
  • September 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
brianjcoleman on Twitter
  • Classix is still holding in the top charts on Apple TV in Canada. #55 Free, #23 Top Grossing. #tvos #appletv #app https://t.co/xuEJiT4rro, Jul 14
  • New Blog Post: "Classix for iPhone, iPad & Apple TV” #iOSDev #ios #swift #swiftlang #SwiftDevs #AppleTV Read here: https://t.co/uF6w3gYOot, May 20
  • New Blog Post: "How to test your app for IPv6 compatibility” #iOSDev #ios #swift #swiftlang #SwiftDevs Read here: https://t.co/SveichSUep, May 6

Recent Posts
  • Classix for iPhone, iPad & Apple TV
  • Tutorial: How to test your app for IPv6 compatibility
  • Tutorial: Testing SSL using Charles Proxy on an iOS Device
  • Tutorial: 3D Touch – Quick Actions in Swift
  • tvOS Tutorial: Top Shelf in Swift
Featured Apps
Classix
Sportsnet
TAGS
tutorialswiftios8iosobjective-cvideostrategygamesframeworknewsappsmonitizeios7applefacebookwatchtoolstvosios9bookdesignsocialapiprovisiontutorialsbooksiapiTunes ConnectIPv6
Search
ABOUT
Brian is a Lead iOS/tvOS Developer from Toronto with over 18 years of multifaceted experience including development, design, business analysis and project management.
MOST VIEWED
Tutorial: How To Use Login in Facebook SDK 4.1.x for Swift
163,489 views
Tutorial: How to test your app for IPv6 compatibility
102,074 views
Tutorial: How to use Auto Layout in Xcode 6
89,234 views
FOLLOW ME
    
Email Subscription
Sign up for my newsletter to receive the latest news and tutorials posted.

Enter your email address:

2013-2017 © Brian Coleman