Tutorial: Adding Simperium to an Existing iOS App

Today we thought we’d show you how to add Simperium data sync to an existing iOS app. We’ve selected Listr, a lightweight, open source app that helps you keep track of things on your wish list. Listr works great for having a list on one device, but what if you wanted to access your wish list on another device, such as your iPad? Simperium can help sync the data as soon as it is saved across devices:

Before we continue with the tutorial, you may want to check out the source code to follow along. You can do so via git in the command line git clone -b update/add-simperium https://github.com/Simperium/Listr.git. Now let’s tweak the code to integrate Simperium!

Note: This tutorial uses Swift, but Simperium still supports Objective-C as well.

1. Configure Project for CocoaPods

Listr wasn’t set up for CocoaPods, so we set up the project to use it so that we can easily include the Simperium iOS library.

  1. Run pod init from the main project directory.
  2. Edit the created Podfile, and add the Simperium pod:
    # Uncomment the next line to define a global platform for your project
    # platform :ios, '9.0'
    
    target 'Listr' do
     # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
     use_frameworks!
    
    # Pods for Listr
     pod 'Simperium', '0.8.19'
    
    end
    
  3. Run pod install​, and then open Listr.xcworkspace in Xcode.

2. Configure CoreData for Simperium

Listr already uses CoreData, which makes it really simple for us to connect Simperium and start syncing the data.

First up, we will add some CoreData overrides so that Simperium can integrate with the existing data model, and sync data when it is saved automatically. First we go into each data model class, such as Item+CoreDataClass.swift, and change its parent class from NSManagedObject to Simperium’s SPManagedObject:

import Foundation
import CoreData
import Simperium.SPManagedObject

public class Item: SPManagedObject {

public override func awakeFromInsert() {
        super.awakeFromInsert()
        self.created = NSDate() //Assigning current date to 'created' attribute.
    }
}

Next, we need to tweak how the app manages CoreData storage with a custom NSManagedObjectContext, NSManagedObjectModel, and NSPersistentStoreCoordinator in the main AppDelegate. We can then configure Simperium and authenticate:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

...

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
     // Configure Simperium
     managedObjectContext = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
     managedObjectContext?.undoManager = nil
 
     simperium = Simperium.init(model: managedObjectModel, context: managedObjectContext, coordinator: getPersistentStoreCoordinator())
 
     // Set the login view's icon
     let spConfig = SPAuthenticationConfiguration.sharedInstance()
     spConfig?.logoImageName = "AppIcon"
 
     // Authenticate will show the login view if no user is signed in
     simperium?.authenticate(withAppID: "your-app-id", apiKey: "12345", rootViewController: self.window?.rootViewController)
 
     return true
 }

// MARK: - Core Data stack
     func getPersistentStoreCoordinator() -> NSPersistentStoreCoordinator {
     if (persistentStoreCoordinator != nil) {
     return persistentStoreCoordinator!
 }
 
     let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask
.userDomainMask, true)
     let documentsDirectory = paths[0]
     let path = documentsDirectory.appending("/Listr.sqlite")
     let storeUrl = NSURL.fileURL(withPath: path, isDirectory:false)
     persistentStoreCoordinator = NSPersistentStoreCoordinator.init(managedObjectModel: self.managedObjectModel)
     do {
         try persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeUrl, options: nil)
     } catch {
         NSLog("Could not create custom store")
     }
 
 return persistentStoreCoordinator!
 }
 
 var managedObjectModel: NSManagedObjectModel = {
     let path = Bundle.main.path(forResource: "Listr", ofType: "momd")
     let model = NSManagedObjectModel.init(contentsOf: NSURL.fileURL(withPath: path!))
 
 return model!
 }()

...

}

You may have noticed the placeholder Simperium app id and key.  You can get one by creating an app here and replacing the id and key with your Simperium app’s values.

That’s all! You can run the app, create an account, and start syncing Listr data to all of your devices. We hope you’ve found this tutorial useful and are inspired to add Simperium to your apps. If you have any feedback, please let us know in the comments!

Happy Syncing!
– The Simperium Team
🔄