Ghostboard pixel

An Introduction To Extensions

An Introduction To Extensions

iOS has always been a very secure operating system. In order to achieve that, apps are running in its own container. In the beginning of the iPhone it wasn’t possible for an app  to communicate with other apps at all. Luckily, this has changed over the years. In iOS 8 Apple has introduced so-called extensions which allow an app to provide functionality in another context.

Hint: This post is using iOS 10, Xcode 8.2.1 and Swift 3.0.2

So how can you provide an extension? An extension is always a target on its own within an app. So in order to ship an extension, you have to ship the whole app to the app store. And in order to create a new extension, you have to create a new target. Then, you can choose from a lot of different extension types:

extensions01

Let’s take a look at some of them:

Extension Types

Very common are the Action and Share extensions. You can use them, if you are tapping the share button:

The row containing Facebook displays Share extensions. These extensions are used to share content – for example by social media or by using a messenger. iOS provides you a standard user interface for this type of extensions. You can use this interface, but you don’t have to.

The row below displays action extensions. They can be used to manipulate content, show it in another context or perform some kind of action with it.

Also very interesting are “Today” extensions. They can be used to generate a widget that gets displayed inside the today view of the notification center. Examples for today extensions are “Weather” and “Stocks” which are provided by iOS:

But there are a lot of other extensions as well – not only for iOS but also for macOS, tvOS and watchOS as well:

  • Action Extension
  • Audio Unit Extension
  • Broadcast UI Extension
  • Brodcast Upload Extension
  • Call Directory Extension
  • Content Blocker Extension
  • Document Provider
  • iMessage Extension
  • Intents Extension
  • Intents UI Extension
  • Notification Content
  • Notification Service Extension
  • Photo Editing Extension
  • Share Extension
  • Shared Links Extension
  • Spotlight Index Extension
  • Sticker Pack Extension
  • Today Extension
  • TV Services Extension
  • VPN Extension
  • WatchKit App Extension

For more details take a look at the App Extension Programming Guide.

A Simple Today Widget Example

After this short introduction let’s create a simple today widget example. We create a new project and add ad new target by choosing “File -> New -> Target…”. Then we choose “Today Extension” from the section “Application Extension”.  And now we can build the app and the today extension will be available. Just open the today view inside the notification center and tap “edit”. Now, you can add the extension:

After clicking “done“, the extension will be displayed in the today view:

You might be wondering where the label “Hello World” is coming from. Just look inside the storyboard file of the extension and you will find the label. So developing this kind of extension is very similar to developing a normal app.

Take a look inside the view controller of the extension:

import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {
        
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view from its nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func widgetPerformUpdate(completionHandler: (@escaping (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)
    }
    
}

You can see a method called widgetPerformUpdate. As the name indicates, this method will be called whenever the widget will be updated.

App Groups

In most cases the today extension displays content that was generated within the corresponding app. But since the app and the extension are two different targets, you can’t share data as you would do it within the same target. Instead, you have to use so-called App Groups which allow you to share content for example by using a UserDefaults container.

Let’s take a look at an example: Open the capabilities tab of your app target and enable the “App Groups” section. Then, add an app group:

As long as you have a valid developer account, this should work without problems. The same step has to be repeated for the extension target.

Now the app and the extension can access a shared UserDefaults container which can be accessed by using the app group name. Open the view controller class of your app and modify viewDidLoad:

override func viewDidLoad() {
     super.viewDidLoad()
        
     let groupDefaults = UserDefaults(suiteName: "group.com.thomashanning.extension.text")
     groupDefaults?.set("A text", forKey: "extensionText")
        
}

Now, we can access these UserDefaults within the widgetPerformUpdate method of the extension:

func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
        
     let groupDefaults = UserDefaults(suiteName: "group.com.thomashanning.extension.text")
        
     if let extensionText = groupDefaults?.value(forKey: "extensionText") as? String {
          extensionLabel.text = extensionText
     }
        
     completionHandler(NCUpdateResult.newData)
}

Note, that you first have to define an outlet for the label. After building the app, we can indeed see the text inside the extension:

 

By the way: It’s not only possible to use shared UserDefaults, but you can also access a shared file directory. If you want to share larger amounts of data within an app group, you should go that way.

Video

References

Title image: @Lyudmyla Nikolenko / shutterstock.com