Understanding Today Extensions

A Today Extension is an extension that adheres to all the rules mentioned before. Most importantly, a Today Extension isn't much more than a view controller that is embedded inside the notification center's Today View.

This means that, whenever your Today Extension is initialized, there is no AppDelegate involved at all. The extension does not have any application life cycle methods such as application(_:didFinishLaunchingWithOptions:). The contents of your widget are added to the Today View through a technique called view controller containment. The concept of view controller containment means that view controllers are embedded in other view controllers. This technique isn't limited to the Today View; you can also use it in your own applications, and its a great way to compose a complex view hierarchy.

If you're using viewcontroller containment, the parent view controller notifies its child view controllers of certain important events. For example, the parent will tell the child when the viewport or trait collection changes.

Because the Today View renders and contains your widget, you can't set the frame for the widget's view yourself. Chances are you're already used to this. Normally, when you're putting a view controller onscreen inside a navigation controller, tab bar, or simply as the only view controller in a single-view application, you generally don't set the frame for a view controller's view.

However, Today Extensions are somewhat different from an ordinary view controller. Usually, when you present a view controller, you want it to fill all the available space. And usually the available space is just about the entire viewport. Today Extensions are a bit more complex because they don't tend to take up an entire screen. They don't take up a set amount of space, and some widgets in the Today View even grow and shrink.

Before iOS 10, a widget would resize itself based on its contents or the size that the widget would set as its preferredContentSize. Since iOS 10, this behavior has changed and widgets have a user-defined compact mode and an expanded mode. The compact mode should normally be about 110 points in height, but in reality this height varies based on the user's text-size preferences.

Because there are no real guarantees regarding the height your widget has available, it's important that you only show the most important information in your widget and it's a good idea to adopt dynamic type in your widget. This makes your widget more accessible by scaling the text inside your widget based on the user's preferences. You'll learn how to do this once we get to implement the widget.

If your widget supports it, your user can switch to the expanded state for your widget. In this state, you have a bit more freedom to set the size of the widget yourself. We'll explore supporting this a bit more when we implement our own widget.

One more key principle of Today Extensions is that the widget never communicates with its host app directly. If you have a widget that the user can tap to go into a detail view, the widget doesn't directly instruct the app to do this. Instead, URLs are used. You can use a custom URL scheme or a Universal Link to achieve this. In several snippets of example code, Apple uses custom URL schemes to achieve this effect. The app we're going to extend in this chapter will work in a similar fashion.

Now that you're completely up-to speed about app extensions, and Today Extensions in particular, it's time to introduce you to the app we're going to extend in this chapter: The Daily Quote. The name of the app probably gives away the entire concept. It's an app that randomly displays a new quote to the user every day. Because this application has new content every day, it's a great candidate for a Today Extension. Let's dive right in.