• This repository has been archived on 11/Mar/2022
  • Stars
    star
    175
  • Rank 218,059 (Top 5 %)
  • Language
    Objective-C
  • License
    Apache License 2.0
  • Created almost 11 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Cloudant Sync iOS datastore library.

⚠️ NO LONGER MAINTAINED ⚠️

This library is end-of-life and no longer supported.

This repository will not be updated. The repository will be kept available in read-only mode. If you are interested in continuing development efforts please see the list of forks for alternatives (e.g. #465).

For FAQs and additional information please refer to the Cloudant blog.

CDTDatastore

Version Platform Build Status

Applications use Cloudant Sync to store, index and query local JSON data on a device and to synchronise data between many devices. Synchronisation is under the control of the application, rather than being controlled by the underlying system. Conflicts are also easy to manage and resolve, either on the local device or in the remote database.

Cloudant Sync is an Apache CouchDB™ replication-protocol-compatible datastore for devices that don't want or need to run a full CouchDB instance. It's built by Cloudant, building on the work of many others, and is available under the Apache 2.0 licence.

The API is quite different from CouchDB's; we retain the MVCC data model but not the HTTP-centric API.

This library is for iOS, an Android version is also available.

If you have questions, please join our mailing list and drop us a line.

Using in your project

CDTDatastore is available through CocoaPods, to install it add the following line to your Podfile:

pod "CDTDatastore"

Note: We only support building on the latest stable release of Xcode

Using in a Swift app

CDTDatastore is useable from Swift out of the box with a few small quirks. Install as per the instructions above, and import CloudantSync.h into your bridging header.

The Overview section below has examples in both Objective-C and Swift.

Example project

There is an example project in the Project folder, for iOS 8.0. To get this up and running independently of the main codebase, a Podfile is included:

$ cd Project
$ pod install
$ open Project.xcworkspace

In order to run the sample project, edit the URL defined in CDTViewController.m: in replicatorURL. Change this to the credentials for your own account and database, ensuring you have _reader, _writer, and _replicator permissions.

Once running you will be able to edit "to-do" items in the app and in your Cloudant database and replicate these changes in both directions.

Running the tests

See CONTRIBUTING.

Tested Platforms

CDTDatastore gets regularly tested on the following platforms:

  • OS X 10.11 (El Captain)
  • iPhone 4S (Simulator), iOS 9.2

Overview of the library

Once the libraries are added to a project, the basics of adding and reading a document are:

#import <CloudantSync.h>

// Create a CDTDatastoreManager using application internal storage path
NSError *outError = nil;
NSFileManager *fileManager= [NSFileManager defaultManager];

NSURL *documentsDir = [[fileManager URLsForDirectory:NSDocumentDirectory
                                           inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [documentsDir URLByAppendingPathComponent:@"cloudant-sync-datastore"];
NSString *path = [storeURL path];

CDTDatastoreManager *manager =
[[CDTDatastoreManager alloc] initWithDirectory:path
                                         error:&outError];

CDTDatastore *datastore = [manager datastoreNamed:@"my_datastore"
                                            error:&outError];

// Create a document
CDTDocumentRevision *rev = [CDTDocumentRevision revisionWithDocId:@"doc1"];
// Use [CDTDocumentRevision revision] to get an ID generated for you on saving
rev.body = [@{
    @"description": @"Buy milk",
    @"completed": @NO,
    @"type": @"com.cloudant.sync.example.task"
} mutableCopy];

// Add an attachment -- binary data like a JPEG
CDTUnsavedFileAttachment *att1 = [[CDTUnsavedFileAttachment alloc]
                          initWithPath:@"/path/to/image.jpg"
                          name:@"cute_cat.jpg"
                          type:@"image/jpeg"];
rev.attachments[att1.name] = att;

// Save the document to the database
CDTDocumentRevision *revision = [datastore createDocumentFromRevision:rev
                                                                error:&error];
// `revision` will be `nil` on failures.

// Read a document
NSString *docId = revision.docId;
CDTDocumentRevision *retrieved = [datastore getDocumentWithId:docId
                                                        error:&error];

If you are using Swift, install the library as per the instructions above and add the use_frameworks! instruction to your target. A bridging header is required if the use_frameworks! instruction is not used.

If you are using a bridging header, include the CloudantSync.h and you should be good to go:

#import <CDTDatastore/CloudantSync.h>

To add, and read documents in Swift, the basics are:

import CDTDatastore

do {
    let fileManager = FileManager.default

    let documentsDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).last!

    let storeURL = documentsDir.appendingPathComponent("cloudant-sync-datastore")
    let path = storeURL.path

    let manager = try CDTDatastoreManager(directory: path)
    let datastore = try manager.datastoreNamed("my_datastore")

    // Create a document
    let rev = CDTDocumentRevision(docId: "doc1")
    rev.body = ["description":"Buy Milk",
                "completed": false,
                "type":"com.cloudant.sync.example.task"]

    // Add an attachment - binary data like a JPEG
    let att1 = CDTUnsavedFileAttachment(path: "/path/to/image/jpg",
                                        name: "cute_cat.jpg",
                                        type: "image/jpeg")!
    rev.attachments[att1.name] = att1

    let revision = try datastore.createDocument(from: rev)

    // Read a document
    let docId = revision.docId
    let retrieved = try datastore.getDocumentWithId(docId!)

} catch {
    print("Encountered an error: \(error)")
}

Read more in the CRUD document.

You can subscribe for notifications of changes in the database, which is described in the events documentation. It's still a bit raw right now:

  • You receive a notification for all new revisions in replication (which can be more than one per updated document).

Replicating Data Between Many Devices

Replication is used to synchronise data between the local datastore and a remote database, either a CouchDB instance or a Cloudant database. Many datastores can replicate with the same remote database, meaning that cross-device synchronisation is achieved by setting up replications from each device to the remote database.

Replication is simple to get started in the common cases:

#import <CloudantSync.h>

// Create and start the replicator -- -start is essential!
CDTReplicatorFactory *replicatorFactory =
[[CDTReplicatorFactory alloc] initWithDatastoreManager:manager];

NSString *s = @"https://apikey:[email protected]/my_database";
NSURL *remoteDatabaseURL = [NSURL URLWithString:s];
CDTDatastore *datastore = [manager datastoreNamed:@"my_datastore"];

// Replicate from the local to remote database
CDTPushReplication *pushReplication = [CDTPushReplication replicationWithSource:datastore
                                                                         target:remoteDatabaseURL];
NSError *error;
CDTReplicator *replicator = [replicatorFactory oneWay:pushReplication error:&error];

//check error

// Start the replicator
[replicator start];
import CDTDatastore
do {

    let datastore = try manager.datastoreNamed("my_datastore");

    // Replicate from the local to remote database
    let remote = URL(string: "https://apikey:[email protected]/my_database")!
    datastore.push(to: remote) { error in

        if let error = error {
            print("Encountered an error: \(error)")
        } else {
            print("Replication complete")
        }

    }

} catch {
    print("Encountered an error: \(error)")
}

Read more in the replication docs including how to use IAM authentication instead of username/password.

Finding data

Once you have thousands of documents in a database, it's important to have efficient ways of finding them. We've added an easy-to-use querying API. Once the appropriate indexes are set up, querying is as follows:

NSDictionary *query = @{
    @"name": @"John",         // name equals John
    @"age": @{ @"$gt" : @25}  // age greater than 25
};
CDTQResultSet *result = [datastore find:query];
[result enumerateObjectsUsingBlock:^(CDTDocumentRevision *rev, NSUInteger idx, BOOL *stop) {
    // do something
}];
let query = [
    "name" : "John", // name equals John
    "age" : ["$gt" : 25] // age greater than 25
]
let result = datastore.find(query)
result?.enumerateObjects { rev, idx, stop in
    // do something
}

See Index and Querying Data.

As of version 0.16.0 the indexing and querying code has been re-written and has more features than the previous implementation. For details about migrating to a 0.16.0+ indexing and query version from a previous version see Index and Querying Migration.

Conflicts

An obvious repercussion of being able to replicate documents about the place is that sometimes you might edit them in more than one place at the same time. When the databases containing these concurrent edits replicate, there needs to be some way to bring these divergent documents back together. Cloudant's MVCC data-model is used to do this.

A document is really a tree of the document and its history. This is neat because it allows us to store multiple versions of a document. In the main, there's a single, linear tree -- just a single branch -- running from the creation of the document to the current revision. It's possible, however, to create further branches in the tree. At this point your document is conflicted and needs some surgery to resolve the conflicts and bring it back to full health.

Requirements

All requirements are included in the source code or pulled in as dependencies via pod install.

Contributors

See CONTRIBUTORS.

Contributing to the project

See CONTRIBUTING.

License

See LICENSE

CDTDatastore classes and TouchDB classes

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Used libraries under different licences

  • MYUtilities is licensed under the BSD licence (portions copied into vendor directory).
  • FMDB, by Gus Mueller, is under the MIT License.
  • Google Toolbox For Mac is under the Apache License 2.0.

More Repositories

1

bigcouch

Putting the 'C' back in CouchDB
Python
565
star
2

sync-android

A JSON-based document datastore for Android applications
Java
267
star
3

nodejs-cloudant

Cloudant Node.js client library
JavaScript
255
star
4

mango

MongoDB API layer for CouchDB
Erlang
200
star
5

python-cloudant

A Python library for Cloudant and CouchDB
Python
163
star
6

java-cloudant

A Java client for Cloudant
Java
79
star
7

meteor-couchdb

Meteor database driver for CouchDB and Cloudant
JavaScript
53
star
8

haengematte

example applications for basic crud features in different languages
Java
45
star
9

swift-cloudant

A Swift Lang client for Cloudant and CouchDB
Swift
42
star
10

sabisu

A sensu web UI powered by Cloudant
JavaScript
31
star
11

cloudant_cookbooks

Cloudant's Chef Cookbooks
Ruby
27
star
12

fabric

Routing and proxying library app for BigCouch
Erlang
20
star
13

mem3

BigCouch cluster membership layer
Erlang
18
star
14

rexi

Lightweight RPC server
Erlang
17
star
15

couch_replicator

Erlang
16
star
16

sensu-trapd

snmp trap to sensu event
Python
15
star
17

jsindexer

An example CouchApp based CouchDB javascript view that creates and inverted index using CouchDB map-reduce
JavaScript
15
star
18

openxc-js

Chrome App for OpenXC
JavaScript
13
star
19

chttpd

A cluster-aware httpd layer for CouchDB
Erlang
12
star
20

twig

Logger
Erlang
12
star
21

monic

Erlang
7
star
22

sensu-run

Execute sensu checks locally on demand
Ruby
6
star
23

sync-cordova-plugin

Cordova plugin for Cloudant Sync for Android and iOS
Objective-C
6
star
24

ilcli

I like command-line interfaces
Python
5
star
25

couch

Erlang
4
star
26

nifile

NIF based POSIX file IO for Erlang
C
4
star
27

lager_rsyslog

An Rsyslog backend for Lager
Erlang
4
star
28

jwtf

JSON Web Token Functions
Erlang
3
star
29

ets_lru

LRU implementation using ETS
Erlang
3
star
30

sobhuza

Implementation of Stable Leader Election algorithm
Erlang
3
star
31

objective-cloudant

Objective-C Cloudant client library
Objective-C
3
star
32

pouch_gpkg

OWS10 GeoPackage to Pouch
JavaScript
3
star
33

hdfs

Open source, first hackish pass at exporting to Hadoop using the _changes feed.
Python
3
star
34

erl_spatial

a wrapper around libspatialindex
C++
2
star
35

ohai_plugins

Plugins for Opscode's ohai, a part of chef.
Ruby
2
star
36

delegated_auth

Allow an external service to choose name and roles for A/A.
Erlang
2
star
37

ddoc_cache

Cache design docs on each node
Erlang
2
star
38

porkrind

Hamcrest matchers for Erlang
Erlang
1
star
39

public-examples

Public Examples
Python
1
star
40

config

CouchDB config layer
Erlang
1
star
41

changes-feeds-example

Shell
1
star
42

fdblucene-perf

Performance tests for fdblucene
Java
1
star
43

gambrelli

Erlang term encoder and decoder for Akka
Scala
1
star
44

wkb_writer

OGC Well Known Binary (WKB) writer in Erlang
Erlang
1
star
45

knit

Erlang tool for generating release and upgrade packages
Erlang
1
star