Payal Gupta

@p.gpt10

All you need to know about Today Extensions (Widget) in iOS 10

Apple introduced App Extensions in iOS 8 and since then they are making a big difference in the world of iOS App Development. Lets get started with some extensions related terminology first.

Terminology

What’s an App Extension?

An app extension lets you extend custom functionality and content beyond your app and make it available to users while they’re interacting with other apps or the system. It is used for some specific task. It is not an independent app.

Extension Point

An extension is tied to a particular area of the system refered to as the extension point. Each extension can have atmost 1 extension point.

Example:

  1. Today Extension is tied to Notification Center
  1. Share Extension can appear only in UIActivityViewController.

Containing App

The app for which the extension is created.

Host App

The app from which the extension is launched

You can get clarity of the terminology in the upcoming sections. Have patience..🙂

Extension Lifecycle

  1. User chooses the app extension from the host app.
  2. System initiates the app extension. Extension displays its view within the context of host app. User performs the required task in app extension and dismisses it.
  3. User returns to the previous context in the host app. Shortly after the app extension performs its task, the system terminates the extension.

Example:

In the above screenshot,

  1. App Extension: Facebook Share Extension
  2. Containing App: Facebook
  3. Host App: Photos App

How App Extension Communicates

  1. Direct communication between app extension and host app. System uses interprocess communication for communication between host app and extension. There is a request from the host app and a response from the extension.
  2. No communication between containing app and host app.
  3. Indirect communication between app extension and containing app. Example, Shared Resources: 1. Framework — to share code 2. App Group — to share data.

Today Extension (Widget)

Widgets are Notification Center extensions. These are simple view controllers with some additional functionality and hence their lifecycle works normally as for other view controllers.

Performance is most important:

  1. Use cached data.
  2. Move expensive operations to background.
  3. Design a simple UI.

Today Extensions in iOS 10

Initially Today Extension was introduced in iOS 8. Later in iOS 10, some significant changes were made to it.

Example: In iOS 8 and iOS 9, Show More/Show Less needed to be handled explicitly by the developers. It was a tedious task since it required constraint and layout handling to adjust the widget’s height according to the content. But in iOS 10, Apple provided APIs to handle such functionality without taking much pain.

How to?

Here I’ll provide you the basic constructs that you require to implement a Today Extension in iOS 10. At the end of this article you can find a link to the Sample.

App Group — Share data with the Containing App

As stated earlier, you cannot directly share data between your extension and its containing app. To share data, you need to use App Group.

Even though an app extension bundle is nested within its containing app’s bundle, the running app extension and containing app have no direct access to each other’s containers.
To enable data sharing, use Xcode or the Developer portal to enable app groups for the containing app and its contained app extensions. Next, register the app group in the portal and specify the app group to use in the containing app.

You cannot use standard UserDefaults to share data between App Extension and the Containing App.

Use standard one for data that is only for Containing App. Use suiteName for data that you want to share between Extension and Containing App. Just don’t persist the same data in both of them. Avoid data redundancy. Use both of them according to the context.

NCWidgetDisplayMode

There exist 2 modes in which you can display data in your widget. These modes are categorized under NCWidgetDisplayMode as compact and expanded.

  1. Compact mode has a fixed height of 110 and
  2. Expanded mode is used for variable height according to your content.

Show More or Show Less buttons are shown in the widget’s top right corner according to the widget’s active display mode i.e. in compact mode, show more is visible and in expanded mode, show less is visible.

widgetLargestAvailableDisplayMode signifies the largest display mode supported by your app.

  1. When set to compact, your app will only support compact mode i.e. show more/show less functionality will no longer be supported and your widget will have a fixed height of 110.
  2. When set to expanded, the app will support both compact and expanded mode and show more/show less functionality will work accordingly.

Handling Height according to Display Mode

NCWidgetProviding protocol provides a delegate method widgetActiveDisplayModeDidChange(_: maxSize:) that handles the size of the widget in compact and expanded mode.

Width of the widget remains same according to the device you are using. There is no provision provided to change it.

Height of the widget can be changed according to the active display mode.

Note: In expanded mode, the maximum height that you can provide to a widget cannot be more than the visible space provided to widgets in the Notification Center.

Updating Widget

To help your widget look up to date, the system occasionally captures snapshots of your widget’s view. When the widget becomes visible again, the most recent snapshot is displayed until the system replaces it with a live version of the view.

widgetPerformUpdate :

  1. called when widget is updated in background.
  2. called before widget snapshot is taken.

Opening Containing App from Today Extension

You can open your containing app from the extension using open(_ URL:, completionHandler:)

You also need to define YOUR_URL_SCHEME in the URL Types of your containing app.

When the containing app is opened from extension, you can get the handle in AppDelegate’s application(_ : url: sourceApplication: annotation: ) method.

Show/Hide Widget from Containing App

In case you need to show or hide the extension depending to the content you want to show, you can do it from your containing app.

Framework — Share code with the Containing App

You cannot directly share the code between your extension and its containing app. To share data, you need to use Framework.

You can create an embedded framework to share code between your app extension and its containing app.
Make sure your embedded framework does not contain APIs unavailable to app extensions. If you have a custom framework that does contain such APIs, you can safely link to it from your containing app but cannot share that code with the app’s contained extensions. The App Store rejects any app extension that links to such frameworks or that otherwise uses unavailable APIs.
To configure an app extension target to use an embedded framework, set the target’s “Require Only App-Extension-Safe API” build setting to Yes.

Unable to Load — Most common issue faced in Today Extension

Unable to load in Today Extension mostly appears when:

  1. You extension crash due to some reason.
  2. It takes more memory than what is provided by the system. (Memory Limit : max 16MB approx.)

Debug your app extension to find out the exact problem.

Refer to Xcode’s Debug Gauge for Memory and CPU utilization.

Things to remember:

  1. Avoid using scroll views.
  2. Doesn’t support keyboard entry.
  3. Must be light weight.
  4. Extension that launches too slowly is terminated by the system.
  5. Low memory limits — (max 16 MB approx.)
  6. Some APIs unavailable to App Extension — sharedApplication object, camera, microphone, receive data using airdrop.

Feel free to leave comments in case you have any doubts.

More by Payal Gupta

Topics of interest

More Related Stories