Adding Share Extensions with Swift
If your app uses a certain type of file, such as images, PDF or just files in general, for internal use or as part of a functionality, then you will definitely need to use extensions in your application to take it to the next level. But what are extensions in iOS?
With the arrival of iOS 8, Apple introduced the well-known App Extensions, a brand new way of interacting with other apps or systems without actually launching it. It makes us able to share files from one app to another, modify a file in a third app and obtain it back already modified in your application. These are some of the more significant examples of what you can do with the “App Extensions”. Although the very secure iOS architecture prevents the use of malicious codes from third-party applications, the use of extensions within our own apps can be the cause of a real headache.
The extensions are not separate applications in our app; they efficiently add extra functionality to our app and focus on a single task. The existing types of extensions are:
Today: an extension that is displayed in the “today” view of the Notification Center that shows brief information and allows you to perform quick and easy tasks
Share: an extension that allows your application to share (and receive) content with users on social networks and other similar sharing services
Action: an extension that allows the creation of custom action buttons in a predefined view in order to allow users to view or transform content originating in a third application
Photo Editing: an extension that allows users to edit a photo or video within the Photos application
Document Provider: an extension used to allow other applications to access the documents managed by your application
Custom Keyboard: an extension that replaces the system keyboard
In today’s example, we will learn how to create a ‘Share Extension’ to receive files from other applications to our own. First we will create a test project where we will add a “table view” that shows the files in the internal folder on our application.
Now we need to add an extension to our project. To do this we go to “File » New » Target” and select “Share Extension”.
Give it a name that is easy recognizable from other applications:
You will be asked for your confirmation to activate the extension that you just created, click Yes (Activate).
You will see that “ShareViewController” class has appeared which inherits
NO from UIViewController like this
For practical reasons, we erase all this and create our own personalized “ShareViewController”. But before we can do that, we must first customize the Storyboard that is linked to this class. In this case, I have deleted almost all the default settings and I created it to my liking.
Once we have the visual display, it is time to add a code to our extension. First, we need to define what type of files we are going to accept in our application. So open the file “Info.plist” with the extension and replace this code:
Which means that it accepts any file. But we don’t want it to accept every possible file, we only want PDF, docx, xlsx type files…. Replace the previous code with this one:
Which means that it will accept files from a URL (e.g. Dropbox) or attachments in mail messages. Now I will go more into detail about the rest of the extension code. First you need to make it inherit UIViewController and add a “importFile” method that contains a code similar to the following:
First, we need to identify what type of files we expect to find
Using an ItemProvider, load the file that you have received in your “ShareExtension”. Copy it to the shared folder in your extension and your main application. Before launching the application, check the shared folder for the files you just imported. Once the file has been copied to said shared folder, you will get a UIAlertController that informs the user and closes the application.
Notice that in order to go back and leave the current ViewController, we do not use a
dismiss as we normally do. Instead we use:
To close the ViewController of our extension. Weird huh? By slightly modifying the code we can download files from DropBox and import them into our application, very much in the same way we can take the files that we import from local files (such as attachments in Mail). Take a look at our project to see how it’s done
We have to enable the groups between our application and our extension in order to share files between them. To do this, go to the ‘Capabilities’ tab and enable the “App Groups” option in both and create an “App Groups” (usually “group.”plus the same bundle that we use in the app). Once created, we must also add this to the extension.
So that’s done, our app now has a “Share Extension” to import files. Now I will explain how to read the files from the ViewController of our app.
ViewController has a “refresh” method to read the content of the shared folder with the extension. Copy them to the internal folder of the application. Once it’s copied correctly, you can delete this file in the shared folder, it no longer serves a purpose here. After all this is done we use another method, in this case “getAllFiles()”, to read all the files in our internal folder and make them pop up in the tableview. How to do this is not within the objectives of this post. I skipped this because I have talked about this in one of my previous posts. Check out the example I am using on GitHub. The end result, should be something like this:
Keep in mind next considerations:
- The “Deployment Target” must be the same in our application and in our “Share Extension”
I- n order to upload a binary to the
Buildof our Extension must match the
Buildof the application; the bundle version of the extension must be equal to the build of our Application and the bundle version string must almost be equal to the version of our application.
- It is very easy to forget to enable “App Groups”, are you sure you checked it?
- Due to the instability of XCode (9), you easily get conflicts while you are preparing your extension. A “Clean” + “Build” will make your life easier.
- If necessary, you can launch your application from your extension by using URL Schemes
- The “UserDefaults” are not shared between your application and your extension. For this, you can use the UserDefaults of Groups so that:
- The images that you add to your Assets will not be loaded by default in your extensions. You must enable the “TargetMembership” for each image.
You can download the complete project on my GitHub repository.
Happy coding! ☺