Creating Today Extension for iOS 8

Original author: Chris Wagner
  • Transfer
  • Tutorial
With the release of iOS 8 , Apple introduced a new concept called App Extensions , with which you can share the functionality of your application with other applications, and from the OS itself.

One of these types of extensions are Today Extensions , also known as Widgets . They provide you with the opportunity to display information in the Notification Center, which is a great way to provide the most relevant information that a user is interested in.

In this article, you will write an application based on the Today Extension that will present the current market value of Bitcoin based on the US dollar.

It has never been so simple and so quick to provide the right information for your users. Let's start!


For those who are not familiar with Bitcoin , this is a digital cryptocurrency that is still in its infancy. In addition to using it for peer-to-peer exchanges and purchases, Bitcoin allows the user to exchange them for other cryptocurrencies such as Dogecoin and Litecoin or for US dollars or Euros.

Since this is a relatively new currency, its market value fluctuates per minute; there were huge peaks and recessions over the entire period of its existence. Thus, this is an ideal candidate for Today Extension, as investors or buyers will want to know the stock price to the nearest second!


Since you are writing an extension, to get started you need a ready-made application; well, it's time to get to know Crypticker.

Crypticker is a simple application that displays the current Bitcoin price, the difference between yesterday and the current price, as well as a graph of price history. The schedule includes a 30-day history; by swiping your finger on the chart, you will see the exact price for a certain day.

The extension will contain all these functions, but you will not be able to see the price for a certain day by swiping your finger on the schedule. There are some links to Today Extensions, especially when it comes to using gestures and multitasking. The gesture is often activated by swiping your finger between Today Extensions and the Notification Center, so you don’t need to have a lot of user experience to complete it.

Let's get to work

You need to download the Crypticker starter project to get started. The project contains Crypticker applications, as described above. In this article we will not focus on developing the application itself, so you will be pleasantly surprised by the shortness of this article. In the end, you will write an extension, but not an entire application.

Compile and run the application. Please note that you will need an internet connection to see the price in real time using the web service.


The application looks like a screenshot; the data displayed will, of course, depend on how things are going on the Bitcoin market. Touching the chart near the bottom, a line appears and displays the price for the corresponding day.

For those who do not yet know BTCThis is an abbreviated form for Bitcoin ; just as USD stands for US dollar. Today Extension will introduce a smaller version of the basic concept of Crypticker.

Theoretically, the Crypticker application has the ability to show pricing for several cryptocurrencies, but our extension is intended only for BTC . Therefore, it is called BTC Widget .

Note: Extensions, by their nature, have only one simple functioning purpose. If you want to display information for another cryptocurrency, such as Dogecoin, it is best to create another widget and with it an application, or develop your UI accordingly, for example, like a Stocks widget .

By the end of the article, your Today Extension will look something like this:


Adding the Target Today Extension The

extensions are created as a separate binary file, received from their host application. Thus, you will need to add the target Today Extension to the Crypticker project.

In Xcode in Project Navigato, select the Crypticker project and add a new target, Editor \ Add Target ... Then select iOS \ Application Extension \ Today Extension . And click the Next button .


In the Product Name, enter BTC Widget , and make sure that Swift is selected in the programming language and that the Embed in Application projectare crypticker . And click Finish .


When prompted, you need to activate the BTC Widget scheme . Because the text indicates that another scheme will be created for you to run in Xcode .

Congratulations! Now BTC Widget will appear in your targets list .


Make sure you select BTC Widget , then the “General” tab, and then click the + button , which is under the Linked Frameworks and Libraries line . As the picture shows:


Select CryptoCurrencyKit.framework and click Add .

Cryptocurrentkit- A custom framework that is used by the Crypticke application to receive prices and currencies from the network. Fortunately for you, the incredibly kind and thoughtful Crypticker developer has applied modular design to code, turning it into a framework so that several targets can use it.

In order to exchange data between the host application and its extensions, you must use a custom framework. If you do not, you will need to duplicate the code many times, and violate the important rule of software engineering: DRY - or, Do not repeat. I will repeat it again: "Do not repeat . "

From now on, you can begin to implement the extension.

Notice, now you have a group in Project navigator, named after your new targeta, BTC Widget . This is where Today Extension code is located by default.

Expand the group and you will see the view controller, storyboard, and the Info.plist file. His target configuration also tells him to load his interface from MainInterface.storyboard , which contains one view controller with an assigned class to TodayViewController.swift .


You will notice that some files that should be in the Today Extension template are missing; for example, as a delegate application. Remember that extensions work inside another host application in such a way that they do not go through the traditional life cycle of the application.

In fact, the extension life cycle is displayed on the TodayViewController life cycle.

Open MainInterface.storyboard and you will see a dark bright background with a light Hello World . Today Extensions have the highest definition images with a light background and light or bright colored text that blends in perfectly with the dark, blurry background of the Notification Center.

Make sure target BTC Widget is selected on the Xcode toolbar , compiled and running. As a result, a window appears asking for permission to launch the application. Xcode will ask you which host application you want to run. Choose Today. This indicates that iOS will open the Notification Center in the Today panel, which in turn launches your widget. The notification center is actually the host application for Today Extensions .


It also allows Xcode to use its debugger while the widget is running.


Here is your widget. Cool, right? Although this is a super-exciting thing, a little more work needs to be done on the widget. It's time to do something interesting!

Note: You may notice many errors related to the use of Auto Layout which are displayed in the console when the widget starts. This is a template issue in Xcode, and we hope that Apple will solve it in the future. Although, do not worry, because you already have your own interface and the ability to use Auto Layout .

Create an interface

Open MainInterface.storyboard and delete the Label . Add a view with a size of 150 points in height and 320 points in width; set it for it in Size Inspector . Move Button, the two Labels and View from the Object Library to the view controllers.

  • Place one of the lables in the upper left corner, and in the Attributes Inspector set Text to $ 592.12 and Color to Red: 66, Green: 145 and Blue: 211. It will show the current market price.
  • Place another Lable to the right of the one you just installed, but leave a box to the right of the button. In the Attributes Inspector, set Text to +1.23 and Color to Red: 133, Green: 191 and Blue: 37. This will show the difference between yesterday's price and current price.
  • Move the button to the upper right view, and in the Attributes Inspector set Image to caret-notification-center and delete the Title.
  • Finally, put an empty view below the two lable and buttons, stretch it so that the bottom and side edges touch the content of the view and set Height to 98. In the Attributes Inspector, set Background to Clear Color, and in Identity Inspector set Class to JBLineChartView .

Note: There is a class called JBLineChartDotView that Xcode can offer when typing, making sure you select JBLineChartView .

Your View and Document Outline should look something like this:


Note: The view is presented in white for visibility in this article. Your view will actually have a dark gray background that models how your view will appear in the Notification Center.

Do not worry about the order in which it is located, as you will be adding Auto Layout soon to properly determine the location.

Now expand the crypticker group toProject Navigator and select Images.xcassets. In the File Inspector , add the subject directory to the target extension by checking the box to the left of the BTC Widget .

This forces Xcode to include the graphic resource directory from the target Crypticker in your target Widget.; this is where the caret-notification-center image that you used for your button is located. If you have the same graphic resources between your container application and the widget, then it is a good idea to use a special directory that contains only resources that can be shared. This will reduce the oversize in your final extension packs, not including images that are not in use.


Return to MainInterface.storyboard and open the Assistant Editor . And make sure TodayViewController.swift is the active file. Add the following code to the top of the file:

import CryptoCurrencyKit

You did the import of the CryptoCurrencyKit framework .

Next, you need to update the class declaration, which should look like this:

class TodayViewController: CurrencyDataViewController, NCWidgetProviding {

This will cause TodayViewController to become a subclass of CurrencyDataViewController , and ensure that it conforms to the NCWidgetProviding protocol .

CurrencyDataViewController is included in the CryptoCurrencyKit and is also used as the main view in Crypticker. Since the widget and application will display similar information through the UIViewController , it makes sense to put reusable components in a superclass, then subclass them, as the requirements vary.

NCWidgetProviding, is a protocol that is specifically designed for widgets. There are two methods for obtaining it that you will implement.

Hold Ctrl and move from the button to our class, just below the class declaration. In the dialog that appears, make sure Connection is selected as Outlet , Type is selected as UIButton , and enter toggleLineChartButton in the Name field . Click Connect .


Then hold down ctrl and move from the button to the bottom of the class this time. In the dialog that appears, change Connection to Action , set Type to UIButton and entertoggleLineChart in the string Name . Click on Connect.


TodayViewController subclasses CurrencyDataViewController , which has outputs for price lable, leble price changes and line chart displays. Now you need to connect them. In Document Outline , hold down ctrl and move from T oday View Controller to price label (with text set to $ 592.12). Select priceLabel from the popup to create a connection. Repeat all this for another lable, selecting priceChangeLabe from the popup. Finally, do the same for the Line Chart View by selecting lineChartViewfrom the pop-up window ...


Auto Layout

In order for your widget to be adaptive, you need to set Auto Layout links. New connections released with iOS 8 are the concept of Adaptive Layou t. The general idea is that a view designed with a single layout can work on different screen sizes. A view is considered adaptive when it can adapt to unknown future metric values ​​of the device.

One of the links you add is to show and hide the chart, and help determine the overall height of the widget. The notification center will be based on the entered data in order to display your widget with the appropriate height.

Choose Lable $ 592.12, and then selectEditor \ Size to Fit Content . If the Size to Fit Content option is disabled in the menu, deselect Lable, and then select it again and try again; sometimes Xcode may work intermittently a bit. Next, using the Pin button at the bottom of the storyboard workspace , set the Top and Leading priority to 8 and 16, respectively. Make sure Constrain to margins is selected.


Select Lable +1.23 and select Editor \ Size to Fit Content again . Then, using the Pin button , select the Top and Trailing relationship , and set the properties to 8.


Select Button, and use the Pin button to set the priority for Top and Trailing to 0, and for Bottom to 8. Width and Height to 44. Make sure Constrain to margins is off.


You need to lower the priority of the lower binding for the button. Select the button, and then open the Size Inspector. Find Bottom Space to: link in the list of links, click the Edit button and change its Priority to 250.

By lowering the priority, you allow the Auto Layout systemchange this binding if he considers it necessary. 250 is an arbitrary value, which turns out to be less than 1000, it is this priority that is set on all bindings by default. This binding should change as soon as the widget is minimized. Having various priority levels in the bindings, you tell the system which connections need to be changed first or last when a conflict arises.


Finally, select Line Chart View . Using the Pin button , select Leading, Trailing and Bottom and in the properties set the value to 0, and the height to 98.


From the Document Outline, select the View controllers view , and thenEditor \ Resolve Auto Layout Issues \ All Views \ Update Frames . This will eliminate any Auto Layout warnings in the workspaces by updating the frames to match the correct bindings. If Update Frames is selected, then you have done everything as needed, and there is no need to run the application.

Since all of your bindings are in place, the last step is to create an output to snap the height of the line chart view. Find the Line Chart View in the Document Outline and click on the triangle to expand.

Then click on the triangle for Constraintsto find the desired snap for height. Select it, and then move ctrl + drag to the Assistant Editor , positioning it just below another outlet. In the pop-up window, make sure Connection is selected Outlet , and enter lineChartHeightConstraint for Name . Click Connect .


Implementing TodayViewController.swift

Now the interface is in its place and what was needed was configured, open the TodayViewController.swift file by selecting it in the Standard Editor.

You will notice that you are working with a standard subclass of UIViewController . Comfortable, right? Although later you will come across a new methodwidgetPerformUpdateWithCompletionHandler from the NCWidgetProviding protocol . You will learn more about him by the end of this article.
This view controller is responsible for displaying the current price, the price difference, for pressing a button and displaying the price history on a line chart.

Define the property at the top of TodayViewController that you will use to track if the line chart is displayed or not:

var lineChartIsVisible = false

Now replace the viewDidLoad () method with the following implementation:

override func viewDidLoad() {
  lineChartHeightConstraint.constant = 0
  lineChartView.delegate = self;
  lineChartView.dataSource = self;
  priceLabel.text = "--"
  priceChangeLabel.text = "--"

This method performs the following actions:
  1. Sets the height for the bar chart "height constraints" to 0, so that it is the default.
  2. Sets self as a data source and delegate to represent a line chart.
  3. Sets some placeholder text on two Lables.

Stay in the TodayViewController , and add the following method:

override func viewDidAppear(animated: Bool) {
  fetchPrices { error inif error == nil {

The fetchPrices method is defined in CurrencyDataViewController , and is an asynchronous call that accepts block terminations. The method executes the request to the web service mentioned at the beginning of the articles to get information about the price of Bitcoin .

The method updates both the Lable and the line chart. Update methods are also defined in the superclass. They simply accept the values ​​obtained by the fetchPrices method and format them accordingly for display on the screen.

Due to the design of the widget, you must also implement widgetMarginInsetsForProposedMarginInsets to provide tabs for custom fields. Add the following code to TodayViewController:

func widgetMarginInsetsForProposedMarginInsets
  (defaultMarginInsets: UIEdgeInsets) -> (UIEdgeInsets) {

By default, widgets have a large field, which is installed in many Apple widgets by default. If you want to fill the entire width of the Notification Center, then you need to implement this method and return UIEdgeInsetsZero , which defines a value of 0 for all parties.

Now it's time to see what happened. Select a BTC Widget Scheme. Compile and run the extension. Select Today as the application to launch when prompted.
  • If the Notification Center does not appear, swipe down from the top of the screen to activate it.
  • If the widget does not appear in the Notification Center, you need to add it via the Edit menu. At the bottom of the Today content view, you can see the Edit button . Click the button to expand the menu of all Today Extensions that are installed on the system. Here you can enable, disable and reorder them as you wish. Turn on BTC Widget if you have not already done so.


Cool, isn't it ?! Your widget now displays real-time Bitcoin prices directly in the Notification Center. But you probably noticed one problem; The button does not work, and you do not see the chart.


Then you need to implement the toggleLineChart method for the button that you added so that it expands the widget view and presents the chart. As the name of the method implies, this button will act as a switch; it will also collapse the view to hide the chart.

Replace the empty toggleLineChart method with the following code:

@IBAction func toggleLineChart(sender: UIButton) {
  if lineChartIsVisible {
    lineChartHeightConstraint.constant = 0
    let transform = CGAffineTransformMakeRotation(0)
    toggleLineChartButton.transform = transform
    lineChartIsVisible = false
  } else {
    lineChartHeightConstraint.constant = 98
    let transform = CGAffineTransformMakeRotation(CGFloat(180.0 * M_PI/180.0))
    toggleLineChartButton.transform = transform
    lineChartIsVisible = true

This method controls the constant value of the Line Chart View anchor height to resize the window. It also applies the unfolding transform to the button, thus accurately displaying the visibility of the chart.

After updating the binding, you need to reload the chart data so that it redraws on the new layout.

You can do this in the viewDidLayoutSubviews method by adding it to TodayViewController :

override func viewDidLayoutSubviews() {

Make sure the BTC Widget scheme is selected , compile and run the application. Then select Today as the application to launch when prompted.

On the left, you will see how the widget appears when the chart is hidden. On the right, you will see how it is displayed when we “opened” the widget. Great, really!


Quickly change the color of the line, and you will have one widget. Add the following to TodayViewController :

override func lineChartView(lineChartView: JBLineChartView!,
  colorForLineAtLineIndex lineIndex: UInt) -> UIColor! {
    returnUIColor(red: 0.17, green: 0.49,
      blue: 0.82, alpha: 1.0)

Verify that the schema that is still selected is correct. Compile and run the application. Select Today as the application to launch when prompted.


Your last requirement is that your widget must support it in order to update its view when it is not displayed, allowing the system to create a snapshot. The system does this periodically to help your widget meet current requirements.

Replace the existing implementation of the widgetPerformUpdateWithCompletionHandler method with the following code:

func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
  fetchPrices { error inif error == nil {
    } else {

This method performs the following actions:
  • It retrieves the current price data from the web service by calling fetchPrices .
  • If there are no errors, the interface is constantly updated.
  • Finally - and in accordance with the requirements of the NCWidgetProviding protocol - the function calls the completion block supplied with the system with .NewData enumeration.
  • In the event of an error, the termination block is called using .Failed enumeration . This tells the system that new data is not available and the existing snapshot should be used.

And now, we have finished creating your extension Today Extension ! You can download the final draft here .

So what's next?

The Notification Center in iOS 8 is your own personalized playground! Widgets have been available on some other mobile operating systems for many years, and now Apple has finally given you the opportunity to create them.

As an initiative developer, you might want to take a look at existing applications again and think about how you can update them with widgets. Go ahead and come up with new ideas for the application that will take advantage of the widgets.

If you want to learn more about creating other types of iOS 8 App Extensions, read our iOS 8 by Tutorials book, where you can learn about Photo Extensions , Share Extensions , Action Extensions, and more!

We cannot wait to see what you come up with, and we hope that your Today Extensions will be at the top of our Notification Centers in the near future!

Also popular now: