Sharing Data Between Applications and Extensions Using App Groups

If you ever needed to share data between your iOS apps and/or your application targets, there's a very easy way to do this using app groups.If you ever needed to share data between your iOS apps and/or your application targets, there’s a very easy way to do this using app groups. In this post we’ll see how to share data between two apps and we’ll even build a small library that will make sharing of data extremely simple. Last week, I wrote about monitoring files on the file system, this library will build on top of DAFileMonitor that I developed for that post. Let’s go…

Sandboxes, Entitlements and Containers

As an iOS developer you already know that iOS apps are sandboxed. Just so we’re all clear, when we say an app is sandboxed, we mean that the access to it is restricted by the system. iOS is built on top of Unix and is using advanced user control on the kernel level to restrict access to your app. For example, if you need hardware resources, like camera, your app needs to ask for it. The same goes for access to the users’ data, like photos. Sandboxing is baked deep into the system and its main reason for existence is that your app can’t go gun-ho crazy and do a lot of damage. Sandboxing is there to protect the system and to protect the user. If your app starts doing damage, for what ever reason, it will only do damage in the sandbox.

You’ve probably seen a file in your project with the extension ‘entitlements’. This is a simple plist file with a list of all the system resources your app requested. We’ll be using this file in our examples.

When I hear a word ‘container’ I immediately think of a word ‘folder’ and that’s exactly what it is. It’s just a folder. Your application container is a special kind of folder created when your app is installed on a device. Your app will get a unique identifier that is different for each device and that unique identifier will be a part of the path to your container (just in case you were thinking you can count on the location of the container to remain fixed across devices). In your app container you have your documents directory, your caches directory, you would save your database there, etc. All the files you save on the file system within your app are all being saved somewhere in the app container.

So what if you want to share data between your apps? Then what?

App Groups

App group is a fancy Apple way of saying ‘shared folder’. If you think of it as a shared folder that all your apps and extensions can access you’d be bang on. You can only access your own app groups. There’s no way for you to access other developers’ app group. And that’s just fine. We’ll be using app groups in our example to pass data around. If you read the article on DAFileMonitor, you can see where I’m going with this 🙂

BBPortal

This is the library we’ll be building here. I’ll cover most of the steps in the post. The library will enable apps and targets to communicate between each other using app groups. Let me show you two demo apps communicating side by side:

All of this might seem like dark magic to you, but it’s actually quite simple. What’s happening in the background is, apps are writing a file in the same app group and they’re using DAFileMonitor to listen for changes in the file. In effect, you create a magical portal where you can push data through and everyone who has the same portal opened will receive the data you’re pushing. Let’s get dirty and fire up Xcode!

The Code

BBPortal is built on top of DAFileMonitor and the code for it is quite simple. It essentially writes a dictionary in the shared container (the app group) and it listens for changes on the same file. Portals are identified by an ID, which is actually a file you write. BBPortal works a lot like a subscribe-notify pattern. When you create your portal you’re implicitly subscribed and are listening to incoming data.

There’s only a handful of instance variables that we need:

When the data is available in the portal, we’ll call the ‘onDataAvailable’ closure. ‘groupID’ and ‘portalID’ are self-explanatory. We have an ‘objectID’ property that we’ll use to filter out the incoming notifications, so we don’t notify the subscriber about the data we pushed. We’ll use the ‘fileCoordinator’ and ‘portalQueue’ to write the dictionary on the file system.

The meat of the class is the ‘send’ method. You can pass Any object into it and it will be sent to other portals:

As you can see, there’s nothing special going on here. We simply add an operation to our operation queue and perform a write operation on it using a file coordinator (hm… come to think of it, there’s probably no need for the operation queue since write operations are coordinated anyway… oh well 🙂 ) We create a dictionary here with the payload we’re supposed to save and the object ID. We’ll be using this object id to filter out our own writes in the file monitor.

When we allocated the class we set up our file monitor:

As you can see, we’re using the DAFileMonitor library here to monitor the file for changes. When the file get’s changed, we read the dictionary from the file location, check if it’s our class who made the changes, and if it’s not us, get the payload. We, then, pass the payload to the closure.

Apart from a couple of utility functions, this is it. This is all you need to pass data between your apps and extensions. I created a quick demo for you, to show you how to use this library. Let’s go over it now.

How To Use It

We’ll create two simple demo apps. I’ll go over one of them, because, they’re mostly the same. If you want to use BBPortal in your project the first thing you’ll need is to enable App Groups. So go to your projects’ capabilities tab and enable them. If this is your first time creating a group, you will have an empty list, select the plus button at the bottom to add a new group (or container, as it’s called by Xcode):

Give it a good id. Something that will include your domain name, for example: group.agostini.tech.whatEver is a fine ID. When you’re finished adding a group you should see something like this:

Believe it or not, you’re all set for using BBPortal. This library is available through cocoapods, so I’ll assume you installed it. I set some basic UI components that I won’t get into here, I’ll just go over the specifics of using BBPortal in the view controller.

The Code

The little demo apps I created are sending a dictionary through one portal and an int through another one. This way the two apps can control each other, as shown below:

Let’s check the left view controller. We’ll go over the slider portal only:

Creating the portal is quite simple. We just need the group ID that we created earlier and a portal ID. When anyone sends data through this portal the ‘onDataAvailable’ closure will get called. Here we’ll extract the data that the other app is sending and set the slider value.

Sending the data is quite simple as well:

We simply pass in the dictionary and that’s it. The other app will receive this dictionary and set its slider value. Feels like magic, right 🙂

Conclusion

Who would have thought that sharing data between apps and targets can be this simple 🙂 I really enjoyed writing this article and creating BBPortal, I only hope you enjoyed reading it. I hope you got something useful out of this article. You can find all the examples on my GitHub profile.

Have a nice day 🙂

Dejan.

More resources

0

Leave a Reply