This post discusses how to use Couchbase Mobile to share data between your iOS App and iOS App Extension across devices. In an earlier post, we discussed how you can use Couchbase Lite as a standalone, embedded data store to share data between your iOS App and it’s App Extension on the same device. In this post, we will extend that to leverage the Sync Gateway to enable data synchronization across the Apps and the corresponding App Extension across iOS devices.

NOTE:  We will be using Couchbase Lite v1.4.1 which is the current production release. But everything we discuss here applies to the newer Developer Preview version 2.0 of Couchbase Mobile.

Background

I’ll assume you’re familiar with developing iOS Apps in Swift and have a basic understanding of integrating Couchbase Lite into your iOS App. This Getting Started guide is a great place to begin.

If you haven’t already done so, please read this related blog post on the basics of App Extensions and how to configure your app to support the same.

As in the earlier post, we will discuss how Couchbase Mobile can be used with a Today Extension. This type of extension, also known as a “Widget”, appears in the Today view of the Notification Center and allows users get quick updates.

Couchbase Lite

Couchbase Lite is an embedded database that runs on devices. It can be used in several deployment modes. It can be used as a standalone embedded database or it can be used in conjunction with a remote Sync Gateway that would allow it to sync data across devices. In this post, we will not go over the details of integrating with Couchbase Lite. The Getting Started With Couchbase Lite blog is a good place to get started on that.

Sync Gateway

The Sync Gateway is an Internet facing component that your mobile apps connect to. It is responsible for data synchronization across the clients, routing and authorization. It can be configured to persist data in a Couchbase Server. In this post we will use Couchbase Server in “walrus” mode wherein the data is persisted in-memory. So in other words, in this demo application, our Sync Gateway will not be backed by Couchbase Server. This is suitable for development purposes. In a real world app, you will probably want to persist your data in a server.

Sample Task List App

Download the sample project from the Github and switch to syncsupport branch.

Our sample app is a simple Task List app that allows users to add, edit, delete tasks. A user can mark tasks as completed. A Today Extension is bundled with the app that shows the top 2 tasks right in your notification center without the need to open the app. The user can mark tasks as completed right from the notification center.

All tasks are stored in a local Couchbase Lite database and synched with the remote Sync Gateway so changes are made available to apps/app extensions on other devices.

This implies that the Container app and the extension will both need access to the Couchbase Lite database which is synched up with the Sync Gateway.

Installing/Running Sync Gateway

 

Some noteworthy items –
– The name of the database is demo
– The Sync Gateway is configured to be deployed in walrus mode. Note that this is suited only for development purposes.
– We have enabled guest access. Note that this is suited only for development purposes. In a real world application, you should disable guest access.

  • First, switch to the folder into which you cloned the sample app repo.

  • Then launch the Sync Gateway with the config file.

Architecture

App Extensions are not standalone apps. They are bundled within an App, referred to as a Container App.  Although App Extensions are bundled in the Container app, they run independent of the Container App in a separate process. App Extensions are launched by other apps that need the extension’s functionality. The App that launches the App Extension is referred to as the Host App.  The extension’s UI is displayed in the context of the Host App.

In our sample app, the CBLiteTaskExtension is the Today widget type App Extension and CBLiteTaskApp is the corresponding container app. The system Notification Center is effectively the host app for our App extension.

Although the Container App and the corresponding extension are independent processes running in their own sandbox, they can share data through a Shared Container.

So this implies that if our Couchbase Lite database is located in the Shared Container, that would allow both CBLiteTaskExtension and CBLiteTaskApp to get access to it. The Couchbase Lite database is then responsible for pushing up changes to the Sync Gateway the usual way regardless of whether the content was locally updated by the App or the Today widget. Likewise, changes pulled in from the Sync Gateway are available to both the App and the Today widget.

Setting up a Shared Container

The Shared Container can be set up by registering a unique App Group and enabling it for use by both the Container App and the corresponding App Extension.

Please review the related post on how to configure your app to use “App Groups”

App Walkthrough

  • Open the CBLiteApp.xcworkspace using Xcode. Although the app should work on Xcode 8.3 and above, I prefer to use Xcode 9 because it includes support for launching multiple simulators which would come in handy while testing the sync capabilities across devices. So if you have the option, please use Xcode 9.
  • Build and Run the App on an iOS simulator by choosing the App Target “CBLiteTaskApp”. Now switch to the Today view of the Notification Center
  • Add your new Extension Widget to the Today View as shown below

  • If you are using Xcode 9, launch the app in a second simulator and add the extension widget to the Today View as shown earlier. So now, you have two simulators running the Task List App.

  • On one simulator, using the app, add a couple of tasks tapping on the “+” button. You will see it updated in the Today widget of the second simulator in real time. If you are running a single simlator, you can switch to the Today widget on the same device. You will notice that the tasks that you added are displayed in the widget.
  • Similarly, on one simulator, mark tasks as “completed” via the Today widget. You will see the status being updated in the corresponding app on the second simulator in real time. If you are running a single simlator, you can switch to the app on the same device. You will notice that the completion status of the

  • Now, we will add a task to the Sync Gateway via the Sync Gateway’s REST API. You will see the new task show up in both the app and the today widget on both simulators all in real time! Pretty cool!

You can use any HTTP client to make the REST API calls to update a document on the Sync Gateway. But I will use Postman.

  • Open a terminal and type in the following curl command that adds a task named “task3” to the database

You should see the newly added task show up on the app and the widget

Code Walkthrough

The app is architectured using the [Model-View-Presenter (MVP)] pattern.

DatabaseManager

The DatabaseManager is the Model, implemented as a singleton class that handles the Couchbase Lite database management functions. This is the class that initializes the Couchbase Lite database in the Shared Container so it is now available to both the App Extension and App processes

Open the DatabaseManager.swift file and locate the appGroupContainerURL() function. This function creates a folder in the Shared Container for use by the app

  1. Return the URL to the shared group container. Group containers are stored in ~/Library/Group Containers/
  2. Create a folder named CBLite in the shared group container.

Locate the configureCBManagerForSharedData() function. This is where we configure the CBLManager object with the URL to the folder that we created in the appGroupContainerURL() function

  1. Create CBLManagerOptions object with the appropriate file protections. A value of completeFileProtectionUnlessOpen implies that read/write access to the file is restricted unless file is open
  2. Initialize the CBLManager with the path to the shared container. Subsequently, when the database is created, it will be created in the shared container.That’s it!

Locate the openOrCreateDatabaseInSharedContainer() function. This is where we initialize the Couchbase Lite database using the CBLManager

  1. Create CBLDatabaseOptions object
  2. Initialize the CBLDatabase using the CBLManager instance that was created earlier. When the database is created, it will be created in the shared container specified by the manager.

That’s it! The Couchbase Lite database is now in the Shared Container that both the App and the Extension can read and write to.

The next step is to enable synchornization with the remote Sync Gateway

Locate the startDBPullReplication() function. This is where we configure the Pull replicator to pull data from Sync Gateway to the Couchbase Lite database.

  1. Create CBLReplication Pull replicator object
  2. Set it to pull documents in continuous mode. This will enable changes to be propagated in real time.
  3. Start the replication

Locate the startDBPushReplication() function. This is where we configure the Push replicator to push data from Couchbase Lite database to the Sync Gateway.

  1. Create CBLReplication Push replicator object
  2. Set it to push documents in continuous mode. This will enable changes to be propagated in real time.
  3. Start the replication

Once you have enabled the replication, you add observers to be notified of changes. This is implemented in the addReplicationChangeObserverForReplicator() function.
With these simple steps, you have the shared Couchbase Lite database replicating changes with the remote Sync Gateway.

TaskPresenter

The TaskPresenter is the Presenter, that handles UI interactions from both the CBLiteTaskExtension task extension and the CBLiteTaskApp app and interfaces with the DatabaseManager. It is the go-between the app/ app extension and the DatabaseManager.

Review the TaskPresenter.swift file. You will see that it implements the CRUD functions to interact with the Couchbase Lite database. But notice that the implementation of these functions uses the DatabaseManager.

What Next?

The post discusses how easy it is for you to use Couchbase Lite as a shared data store between your iOS App and corresponding Today App widget. With the shared database syncing with remote Sync Gatway, we can now replicate changes across the apps/ app extensions across multiple devices.

If you have any questions, feel free to reach out to me on Twitter @rajagp or email me priya.rajagopal@couchbase.com. If you would like to suggest improvements, submit a pull request to the GitHub repo. You can learn more about integrating with Couchbase Lite in this Getting started with Couchbase Lite blog.

The Couchbase Forums are another great place to post your questions.

 

Posted by Priya Rajagopal, Developer Advocate, Couchbase

Priya Rajagopal is a Mobile Developer Advocate for Couchbase, living in Ann Arbor, MI. She has been professionally developing software for over 18 years and was most recently the Director of Mobile Development at a startup. Although her current interests lie in mobile development, she has previously worked on a range of technologies including IPTV, Social TV, targeted advertising, network management , RESTful architectures and platform security. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV architectural specifications.
She has spent a decade in software R&D and is a co-inventor on almost 2 dozen US patents.

Leave a reply