With App extensions iOS provides us with a powerful way to make the core functionality of our app available for use from system apps and apps from other developers. Instead of switching between apps they provide the user with an opportunity to use your app in the context of another app. With a share extension for example you could share images from the photos app straight to your app.

There are several types of extensions you could create for your app. Each having its own specific purpose and part of the system it is exposed from, called an extension point. Share and Action extensions for example are made available through the system share sheet.

How does it work

An app extension is an app of its own and runs independent from your app, also called the containing app. Since it runs in the context of another app, the host app, it has a different lifecycle compared to a normal app. It consists of several steps. Let’s look at a scenario where a user wants to share some images from the photos app:

  1. After the user has selected some images and has tapped the share button the photo’s app will instantiate an UIActivityViewController and present it to the user.

  2. Now the user can pick from a list of share extensions that accept images as input. Once the user selects your app the photos app will create an NSExtensionContext and request the system to open the extension. An NSExtensionContext contains all the information that the extension needs to do its job and allows for communication between the host app and the extension and vice versa. The system will handle the request by instantiating the principal view controller, the first view controller in your extension, and provide it with the extension context.

  3. At this point the extension will launch and display its UI in the context of the host app.

  4. In this step the user will interact with your extension. After that they have the choice to either finish or dismiss the extension. When an extension is finished it needs to communicate this back to the host app by completing the request. Dismissal is communicated back to the host app by calling the cancel method with an appropriate error. Both communication is done through the extension context.

  5. The host app handles the completion or cancellation of the request and tears down the extensions UI. After that the system will terminate the extension.

Make your app ready for an extension

When writing an extension you probably want to reuse parts of your core business logic layer or some UI elements from your main app. You can do this by creating embedded frameworks, for example one for core business logic and another for common UI elements. Some API for example UIApplication is not available from an extension. By setting the "Require Only App-Extension-Safe API" to YES in the frameworks build settings the compiler will raise an error if you attempt to use unsupported API in your framework. Once you extracted the code that you want to reuse in a framework the process of adding a new extension is not so complicated. Added benefits are that it makes your code more modular, it lets you make use of the internal access level and allows you to work on certain parts of your app without compiling the entire app.

App Groups

Just like how different apps don’t have access to each others data an extension by default does not have access to your main apps data. In order to share data you need to create an App Group. When both your app and extension are added to the same App Group they both get access to a shared directory where you can store data. Because your app and extension could be running at the same time it is important to safely coordinate writing and reading to shared files. If you use Core Data together with sqlite you will get this for free.

Defining your UI in storyboard, XIB or Code

No, I’m not going tell you what I think is the best way to create the user interface of your app. I believe that all of them have their pros and cons and that you should always pick the right tool for the job. In the default Xcode template the principal view controller is defined in a storyboard. If you want to go for a XIB or pure code you can do this by adding the NSExtensionPrincipalClass key to the extensions info.plist while removing the NSExtensionMainStoryboard key value pair. NSExtensionPrincipalClass should hold a string value with the name of the primary view controller. The next step is to mark that view controller as @objc to make it accessible to the Objective-c runtime:

@objc(PrincipalClassName)
final class PrincipalClassName: UIViewController {
...
}

Writing unit tests

It is not supported to run unit tests inside an app extension. So how can we write unit test for our extension? The answer is easy. Since you most likely will create an embedded framework for the core business logic of the app you can easily test that code in isolation. Extension specific code that you want to test most likely revolves around the NSExtensionContext. By moving that code into helper objects you can test that part of your code as well.

Conclusion

There are many different app extension you can create for your app. Because they provide users with a way to use your app in the context of another app they can be powerful and make your app stand out.

Contact me on Twitter @kairadiagne if you have any questions, comments or feedback.