Privacy Policy Update

As part of our commitment to privacy and transparency, we’re updating our Privacy Policy for Simperium.

“Your privacy is critically important to us.” These are the first words of our Privacy Policy, and words we live by when designing and building our products.

Starting on September 24, 2018, Simperium will be covered in our Privacy Policy for the products and services from us, the folks at Automattic. No more fragmenting: We’re retiring Simperium’s separate Privacy Policy — our privacy practices should be straightforward and easy to understand, so now you only have to understand one.

Here are some of the other updates you’ll see:

  • Our Privacy Policy includes real-world, concrete examples to give you a clearer picture of how we collect and use personal information.
  • We provided more information, in the Choices section, about how you can limit and control the data that you provide to us when you use our services.
  • There’s also added information about your data protection and privacy rights, how long we keep information, and how we handle transfers of personal data outside the EU.

Our new Privacy Policy will take effect on September 24, 2018. We’re announcing the update now, to give you time to take a look at it.

If you continue to use our services on or after September 24, 2018 you acknowledge that your use will be subject to our new Privacy Policy.

And we’d love it if you follow us on privacy.blog for more information about privacy and transparency at Automattic.

***

Although we updated the Privacy Policy, our core values remain unchanged: We strive to be fully transparent. We keep the data we have a reason to keep. And we are thoughtful about how we collect, use, and share personal information.

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
🔄

What We Did Last Summer

Happy autumn from the Simperium team! Over the last few months we’ve been hard at work improving the service. Here’s what we’ve been up to.

Performance improvements

We started looking into ways to improve performance in the Simperium architecture after we’d experienced a few hiccups earlier in the summer. We temporarily suspended new registrations to allow us to focus on making improvements while still supporting the current apps on the platform. Now, after we’ve fixed some limits in the database system, things are running very efficiently — in fact, sync is faster than ever before!

New plans

We’ve adjusted our plan tiers — they’re now based on the amount of requests an app has made, not on the number of app users. We believe these new plans will provide a better value for app developers, and help us build a bright, sustainable future for Simperium. Check out the pricing page for more info.

We’re ready for your apps!

Now’s a better time than ever to get your apps on Simperium. Registration for new developers has reopened. If you’re new to the platform, try out Simplenote on your favorite devices to see Simperium in action. To date, Simplenote has made over 17 billion requests on Simperium!

If you’re ready to dig deeper into how Simperium works, check out our Simpletodo tutorials.

Let’s keep in touch

Have any questions about Simperium? We’re always here to help.

Happy Syncing!
— The Simperium Team

TicTacToe: Multi-device Syncing part #2

In the first part of our tutorial, we discussed the data model we’ll use to power a multi-device TicTacToe game.

We also learned how to integrate Simperium into an iOS app, and how to authenticate our clients by means of a pre-generated token.

One of the biggest technical challenges of this app is: suppose our users have a Match initiated between two players. In our current data model, this is directly translated into: the two clients each have a Player object in the Player bucket, and there is also a Match object linking both players.

Due to the nature of mobile devices, any of the clients can suffer a network disruption at any-time (the device itself might even shutdown due to low battery!)

So… how do we notify our users that their opponents went offline?

1. Simperium’s Presence

Presence is one of the coolest features offered by Simperium. What does it do, exactly?

The presence feature turns a bucket into an ephemeral store. There are two options:

  • User Presence
    Whenever a given user gets disconnected from Simperium’s backend, all of the objects he inserted into buckets with user presence enabled will be automatically deleted. No client interaction is needed, other than the disconnection event itself!.
  • Client Presence
    It works exactly the same way as User Presence, but it is client (or connection) based instead. In Simperium presence’s jargon, a client is represented by a single connection to Simperium. Let’s suppose that someone has both an iPad and an iPhone running the app, these would be two separate clients. Objects created by the iPhone then, would be removed when the iPhone disconnected, but objects created by the iPad would remain as long as the iPad stayed connected.

In our particular scenario, due to our decision to automatically authenticate every device with the same pre-generated auth-token, we’ll need to enable Client Presence in both the Match and Player buckets.

By toggling client presence on, whenever a device running our game goes offline, Simperium will automatically remove all of the Player and Match entities that were created by that device. 

In order to toggle presence for a given bucket, we’ll need to run a simple curl request:

curl -H 'X-Simperium-Token:APP_ADMIN_TOKEN' \
    https://api.simperium.com/1/APP_ID/__options__/i/BUCKET_NAME \
    -d '{"presence":"client"}'

The APP_ID and APP_ADMIN_TOKEN are both available in your Simperium application’s dashboard, as seen here:

SimperiumAdminKey

Since we require client presence to be enabled in both, Player and Match buckets, we’ll need to run two curl requests.

Once that’s ready, Simperium’s backend will make sure that whenever a client goes offline, all of the objects that were inserted by that client are removed.

2. Signaling Player’s Presence

In order to signal a Player’s presence, let’s insert a new Player entity into CoreData, whenever the app becomes active:

Simperium* simperium	= [[TTAppDelegate sharedDelegate] simperium]
Player *player			= [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Player class]) inManagedObjectContext:simperium.managedObjectContext];
player.playerID			= simperium.clientID;
[simperium save];

// Keep a reference to the player
self.player = player;

We’ve already written the code that will disconnect the WebSocket when the app becomes inactive. When that happens, we can expect the Player entity to be deleted (due to our presence settings): all we need to do is to clear the reference to the player instance!

3. Initiating a Match

We’ve discussed before that a match entity will be a simple object that carries the playerID of the involved parties, plus an object representing the TicTacToe board itself. It’s time for us to discuss some application logic…

A match should be initiated when:

  • The app is just launched.
  • Your opponent is removed from the Player’s bucket: maybe he closed the app, his device was shutdown… or he just lost connectivity!
  • The match in which you’re playing suddenly gets removed. This will happen if your opponent initiated the match, and signed off from Simperium’s backend.

An opponent is eligible if:

  • He is not already playing a match with someone else.
  • His playerID is not the same as our own playerID. Otherwise we’d be initiating a match with ourselves!.

All of these conditions can be easily checked, locally, by means of a couple CoreData queries. You don’t need to perform a single backend request: Simperium informs you of any changes to the data.

Code for the entire startMatch method implementation is available here.

4. Listening for new changes

Our application logic is based on two simple data structures. In order to react accordingly to the game state as new changes come in, we’ll need to setup our two Simperium Bucket’s delegates (Player and Match) as follows:

- (void)listenForBucketUpdates
{
	Simperium *simperium	= [[TTAppDelegate sharedDelegate] simperium];
	NSArray *buckets		= @[ NSStringFromClass([Player class]), NSStringFromClass([Match class]) ];

	for (NSString *name in buckets)
	{
		SPBucket *bucket	= [simperium bucketForName:name];
		NSAssert(bucket != nil, @"Bucket not initialized");

		bucket.delegate		= self;
	}
}

You can take a look at the entire delegate implementation here. The different events that are being handled are:

  • Player Inserted
    We will simply refresh the label that displays the number of active players.
  • Player Deleted
    When a player gets deleted, we’ll need to check if the playerID is the same as our opponent’s playerID: if our opponent was removed, we’ll need to move on and try to begin a new match with another player.
  • Match Inserted
    When a new match event gets triggered, we’ll need to react only if our own  playerID is equal to either the crossPlayerID or the circlePlayerID.If that condition is affirmative, and we’re not currently in a match with another player, we should proceed with accepting the new challenge, and just refresh the UI. However, if we were already in a match with another player, we’ll simply delete the new Match object, and let the opponent realize that we’re busy!.
  • Match Updated
    Our app will have, all the time, the ID of the match we’re currently playing (if any). Whenever our own match is updated, we’ll just refresh the interface. If it’s our turn, the user will get to place a cross (or a circle). If not, we’ll have to wait for our opponent.
  • Match Deleted
    A match can be deleted for a variety of reasons: maybe our opponent went offline, or we initiated a match with a player that was already busy.
    Whenever that happens, we’ll need to refresh the UI, and begin a new match with someone else.!

5. Sync’ing the GameBoard

The TicTacToe board itself is represented by a NSArray instance with 9 NSNumber’s in it.  We’ve defined a handy NS_ENUM to specify the allowed matrix values: empty, circle, and cross.

We’ll rely on our Match entity just as a Transport Object: whenever there is a change that requires the UI to be refreshed, we’ll feed our TTGameBoard instance with the updated match.matrix property, and simply request our TTBoardView object to get refreshed.

You can check out the code for refreshing the user interface here.

6. Full Source Available!

You’re welcome to take a look at the final project. Note that you should open TicTacToe-Final.xcodeproj to get the final version of the project.

Got any questions? we’d love to help! Please leave a comment, ask a question, or post an issue, and we’ll get back to you shortly.

TicTacToe: Multi-device syncing with Simperium!

Simperium is a cross platform framework that allows you to seamlessly sync data through multiple devices.

Tic Tac Toe is one of the simplest games you can possibly think of: two players take turns to place a piece (either a cross or a circle) on a 3×3 matrix. The first player that succeeds in placing three marks in either a horizontal, vertical, diagonal or antidiagonal wins the game.

We have built a single-device Tic Tac Toe game for iOS: source code available here. In this tutorial we’ll be learning how to integrate the Simperium framework, and how to enable multi-device data synchronization without writing a single line of backend code.

Our approach to implement the data model will be straight forward. We will maintain two collections:

Players:

Each player will have a unique ID, and will make sure that as long as the app is active, its uniqueID will be present in the Players collection. We will rely on this mechanism to initiate a match between two players.

Match:

The match object itself will have three attributes: the ID of both players, an array representing the status of the gameboard, and an extra flag we’ll use to indicate which player should perform the next move.

Let’s dive into the details!

1. Integrating the Simperium Framework

First of all, we’ll need to add drag the Simperium.xcproj file to our TicTacToe project, as seen below:

Drag Simperium Project

Once ready, let’s make sure we’re linking the required frameworks:

Required Frameworks

Since Simperium is an Objective C framework, we will need to instruct Xcode’s linker to work with Objective C libraries as well. In order to do so, let’s add the ‘-ObjC‘ string in the Other Linker Flags, under the project’s Build Settings, as seen here:

LinkerFlags

At last, we’ll need to add Simperium as a target dependency, in the Build Phases section of our project:

2. Updating our Data Model

Simperium is designed to listen to your CoreData Context, and efficiently sync delta’s through the network.

As a requirement, the classes you want to sync must subclass SPManagedObject -instead of NSManagedObject-.

We’ll need to also store two extra attributes per object, used internally by Simperium: simperiumKey and ghostData, both of NSString kind.

Let’s open our Data Model, and update both, Match and Player entities, accordingly:

1. MatchSchema

2. PlayerSchema

3. Adding a New Simperium App

We’ll need to signup for an account at Simperium’s website. Once there, let’s add a brand new app. We’ll need both, the AppId and AppKey, to initialize our instance of Simperium:

NewApp

There are several ways in which you can implement user authentication: the framework itself already provides a customizable User Interface to perform Signup and Sign-In.

However, in this particular project, we want to offer a signup-free experience: we want our users to be able to begin playing Tic Tac Toe, as soon as the app finishes launching.

In order to do so, let’s pre-generate a user token: every instance of this game will share the same user. You can find the Generate Token button in the Browse Data section of your app:

GenerateToken

4. Updating our CoreData stack

One of the benefits of using Simperium’s library is that Core Data disk operations are performed in a background thread, automatically, by the library. As a requirement for this to work, the Main ManagedObjectContext must not have its persistentStoreCoordinator set.

In our TicTacToe game, we’ve wrapped up all the CoreData initialization code in a single class, called TTCoreDataManager (Header | Implementation). The only difference with a regular CoreData stack initialization can be seen below:

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

// persistentStoreCoordinator must be nil on the main context!:
// [_managedObjectContext setPersistentStoreCoordinator:coordinator];

5. Starting Simperium

We’ll be initializing and authenticating our Simperium instance in the AppDelegate itself, as soon as the application:didFinishLaunchingWithOptions: method is executed:

- (void)startSimperium
{
	TTCoreDataManager* manager = [TTCoreDataManager sharedInstance];

	self.simperium = [[Simperium alloc] initWithModel:manager.managedObjectModel
											  context:manager.managedObjectContext
										  coordinator:manager.persistentStoreCoordinator];
}

- (void)authenticateSimperiumIfNeeded
{
	if (self.simperium.user.authenticated) {
		return;
	}
	
	[self.simperium authenticateWithAppID:TTSimperiumAppId token:TTSimperiumToken];
}

After calling the two routines outlined above, we’ll have a Simperium instance initialized with manual authentication, and our CoreData stack will be ready to begin operating.

We must also call the method authenticateSimperiumIfNeeded everytime the app becomes active, and signout from Simperium’s backend when the app becomes inactive.

We’ll rely on the following lines of code to do so:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
	[self authenticateSimperiumIfNeeded];
}

- (void)applicationWillResignActive:(UIApplication *)application
{
	[self.simperium signOutAndRemoveLocalData:YES completion:nil];
}


6. Next Up…

At this point we have a fully functioning TicTacToe game, we have successfully integrated the Simperium Framework, and we’re automatically authenticating the user when the app is brought to foreground (and logging off when the app is closed).

In the second part of this tutorial, we’ll learn how to signal our presence, initiate matches between two players, and how to sync our board… everything, just with Simperium Sync.

Stay tuned…!

Learn more about how to integrate Simperium into your iOS app.

Simperium joins Automattic

As mentioned in our post on the Simplenote blog, Simperium has been acquired by Automattic! We’re really excited about this and what it will mean for the platform.

Automattic and WordPress are huge proponents of open source software so we’re happy to be able to go forward with our plans to open up the code, starting with the iOS and JavaScript client libraries. In the short term we’ll also be moving to faster hardware, so overall performance and stability of the hosted service should improve.

We’re going to keep expanding Simperium as a tool for building apps. Adding Simperium to apps that can work from a local datastore lets you automatically synchronize data across different instances and platforms. This way of building apps feels natural, a model where the developer can focus purely on the data itself, not networking or APIs. Synchronizing data is just part of the problem though. We’ll be adding better support for things like binary syncing and collaboration, along with a wider variety of client libraries.

Automattic is a distributed company with employees all over the world. They understand the value and importance of collaborative tools. While Simperium currently provides a great way to synchronize data, we also want to make it easier to do things like creating and managing groups of people that need access to the same data, sharing presence information, and showing authors of changes. These are problems that come up again and again when building a collaborative app.

There are still plenty of challenges along the way. If these problems sound interesting, you might consider working with us from wherever you may be in the world.

Open source progress

While working with developers over the past several months, a common request has been access to the source code for customization, extension, and to help with bug hunting. As previously promised, we’ve provided some developers with early access to the source code for our iOS library, and intend to make it publicly available soon under the MIT license. Unobfuscated source code for our JavaScript library will also be made available.

Our pricing and open source strategy

It’s been a month since we launched our beta. Over 1300 developers have signed up to move data with Simperium, and we’re working hard to help you release live apps to production.

We spoke to a lot of you over the past few weeks. We know trust is key. You can’t commit to a service without knowing how it sustains itself, or what will happen if it goes away. With that in mind, we’re announcing pricing today together with our open source strategy.

Pricing

The Basic Plan is free and gives you access to all features for development and prototyping, and up to 2,500 active users per month for production.

Beyond that, a Pro Plan supports 2,501 to 75,000 active monthly users for $99 to $1499 per month. For those with more than 75,000 active monthly users, or if your needs don’t map well to active users, a Premium Plan is available with volume discounts and custom pricing.

All plans include everything you need to move structured data across mobile, web, and your backend services, including persistence, versioning, firehose access, and conflict resolution on our hosted servers. Support for large binary data (like images and audio) is coming later.

Open source

Sometimes a hosted solution isn’t appropriate. Or perhaps you need maximum confidence and control. To that end, we’re open sourcing Simperium starting with our client libraries, and followed by our protocol with a reference server implementation.

Thanks to everyone who gave us feedback. We really appreciate it.

On Moving Data

It’s been over a week since we launched Simperium to the public, and we’re really happy with the response so far. Throughout our development we spoke to dozens of developers, from independents to very large companies. We blended your feedback with our experience building Simplenote to create a service that focuses entirely on the data layer. This means we focus on the tough problems associated with moving data among devices, people, apps and backend services.

Developers seem to appreciate this focus. In practice, it means that going up the stack, Simperium can integrate with tools like Core Data, Backbone.js, and PhoneGap. And going down the stack, Simperium can work with providers like Heroku while integrating with services like Twilio and Urban Airship. We believe this downward flexibility is particularly important. You can create unique services that help your app stand out, and you maintain control of your data (compared to services like iCloud that lock it all away).

That’s the developer perspective. But we’re product people at heart. Simperium arose from Simplenote, which itself arose from our frustration with moving text between our computers and our phones. The lack of a good solution pained us. Our ultimate motivation today, as it was then, is to improve the lives of users.

When you use Simperium as your data layer, your users will never be blocked by network progress indicators. They’ll enjoy access to their data across all their devices. They’ll be able to work offline with full read/write access. And they’ll be able to share and collaborate with the simple act of associating an email address with some data.

That’s the world we want to live in. All these goals (and more that we’re not talking about yet) are about moving data. We see an opportunity to focus on moving data the same way Google focused on searching data, and we look forward to the many challenges and discoveries that lie ahead.