(Part 1 of 3)
The article by Vasyl Khmil is dedicated to iOS extensions. It’s only the first part of his broader work on this topic, and we are going to publish parts 2 and 3 later on.
Vasyl is a software engineer who came to N-iX about a year ago. He is working in mobile development mainly specializing on iOS applications and currently involved in RSS reader development for iLaks, iOS application redesign for SpamDrain and ThickButtons projects.
What is Extension?
In general terms, Extension is a special program that lets you to extend custom functionality and content beyond your app and make it available to the system or to users while they’re using other applications. As iOS 8 was released, it enabled programmers to create their own Extensions which was an opportunity to develop something brand new. Extensions allow to perform a specific tasks inside an app such as sharing some content directly to social networks or using a custom keyboard instead of the system keyboard, as it was previously possible in Android, or adding custom information to Notification Center.
Custom Keyboard and Today Extensions
Extensions can give your applications a completely new look and features while making them clearer and easier to use. They can improve user experience and help you to increase the download rate of your app. As for developers, Extensions offer a new horizon for exploring and the opportunities to deliver new functionality.
Each Extension is unique and their implementation may vary. In this part we will try to understand what do all the xtensions have in common and explain how to facilitate working with them.
Lets start!
Starting a development of a custom Extension, you should keep in mind that Extension is not an independent app and it could be delivered to the App Store only as a part of other standard application bundle. This application is called a Containing App, while an application that user chooses to execute extension – a Host App. A Host App runs an Extension and transfers user`s requests to it, while Extension processes the received data and sends the response back to the Host App if it is needed. An Extension typically terminates soon after it completes the request it received from the Host App. The pictures below show how it works.
Containing App should have logical content to pass Apple Review and in most cases this is not a problem because Extensions are only add-ons to the existing applications. But there are few cases when the main subject of implementation is the Extension itself (eg. Custom Keyboard). Then it becomes unclear what kind of content should be placed in the Containing App to pass the review. One of the most simple and user friendly options to resolve this issue is to fill the Containing App with a setup guide o with an Extension presentation. As an Extension setup may not be very simple, and users do not yet consider them something familiar, putting a setup guide or user manual into a Containing App will make your Extension more user-friendly and increase the chance that it will not be removed after the first minute of usage due to a complexity.
Relationship challenge
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. You can’t use a code from an Extension in a Containing App and vice versa. This limitation was set due to the fact that an Extension and a Containing App are compiling in separate binaries, making it possible to address the Extension without running the Application. However the problem occurs when the code should be used on both sides. For example, if an Application is using Today Extension for displaying custom information, then the code that works with this information should be available both in Application and in Extension.
One possible solution is to copy the code twice, but it is definitely not the desired option. More professional way to solve the issue is to put simultaneous code into Cocoa Touch Framework. In this case, the code is located in one place which makes it easier to work with and at the same time it can be used on both sides simply by connecting the framework to the Application and to the Extension.
Relationship: Next level
Even if you share code using Cocoa Touch Framework, it doesn’t provide an opportunity to exchange data directly between the Containing Application and Extension which is often a vital necessity. For example, let`s take a simple Today Extension that displays information from the Application (a Reminder). As all Reminder’s messages are generating in a Containing App and displaying in Today Extension, we need a shared container for data exchanging. And there is one. It is called an App Group, and you can enable it for the Extension and the Containing application in Xcode 6 Capabilities menu. Then you can use this container to share your information. When you set up a shared container, the Containing App and each contained App Extension that you allow to participate in data sharing have read and write access to the shared container. To avoid data corruption, you must synchronize data accesses. In code you will work with App Group container using NSUserDefaults class.
Suite name here is your shared container unique identifier. If you have previously worked with standard User Defaults container, using an App Group container would`t be a problem for you.
An app extension’s container is separated from a containing app’s container
However if you want to share files, it’ll be difficult using the approach described above. You need to read the data from file and write it into a shared App Group container on one side, then read data from shared App Group container and write it into the file on the other. But we can more likely get URL or path to our App Group container shared directory by using method containerURLForSecurityApplicationGroupIdentifier(_:) of NSFileManager class.
There is also an opportunity to open the Containing App from the Extension by using openURL(_:completionHandler:) method of the NSExtensionContext class. You can’t put all data there, but you can make it posible to open Containing App from the extension where all the information is. It is usefull for example for Today Extension or for those applications which have in-app purchases.
In order to use this aproach you need to define URL scheme for Containing application in Info settings
and if you want to handle this process from Containing Application you need to implement application(_:openURL:sourceApplication:annotation:) method in your AppDelegate class(UIApplicationDelegate protocol). As a result, you will get a URL from previous example and a bundle identifier of the app, that is required to open URL. So, if you need to handle more than one request, for example, one to view purchases and one to view some detailed information, you should create two URL schemes, and open a correct view due to URL paramether in URL handling method, that is described above.
All the relationships, explained above can be demonstrated by this simple picture:
To be continued…