SlideShare a Scribd company logo
Writing Mobile
Applications with
Couchbase
Knoxville Cocoaheads
March 2016
Who is this guy?
• Mike Hagedorn
• Language Polyglot
Why Couchbase?
Changing face of IT Demands
HA

Scalable

Agile, Schemaless

CB: Synching, Admin GUI, SDKs
Couchbase History
Couchbase Terms
• Node
• Cluster
• Bucket
• Document
• View
Couchbase Components
Mobile embedded local db with sync

Gw internet facing component

Server: Ent grade nosql db
Couchbase Server
Couchbase Lite
Couchbase Lite is an embedded JSON database
that can work standalone, in a P2P network, or as a
remote endpoint for Couchbase Server.

Embedded

All IO is local

Syncs are transparent in background

Disconnected operation

NO PUSH

NO Network
CBL
Device 1
CBL
Device 2
CB
Server
Cluster 1
with
GW!
Sync Gateway
CBL
Device 1
CBL
Device 2
CB
Server
Cluster 1
Data
Needed
Here!
?
Remote Data Center
SGW
Couchbase Model
• An object oriented wrapper on top of
CBLDocument
• Somewhat like NSManagedObject
Couchbase Challenges
• Complicated Queries are Hard
• Views!
Getting Started
• DL Couchbase Lite Framework
• Add CouchbaseLite.framework to your project
• There is no step 3
Initialization
//AppDelegate
CBLManager *manager = [CBLManager sharedInstance];
NSError *error;
self.database = [manager databaseNamed:kDBName error: &error];
if (error) {
NSLog(@"error getting database %@",error);
exit(-1);
}
Database
Rockets
Name Weight Diameter Cd
alpha 29 25 0.75
hawk 35 30 0.8
Document
{
"coefficientFriction": 0.75,
"diameter": 25,
"name": "alpha110",
"type": "rocket",
"weight": 23
}
# Bb6YvfoCH7NIgsVDtgjE7O
Unique ID

May contain binary attachments
Database View
//RootController or CBModel
//Define a view that only returns documents of type ‘kRocketDocType’
CBLView* view = [db viewNamed: @"rockets"];
if (!view.mapBlock) {
// Register the map function, the first time we access the view:
[view setMapBlock: MAPBLOCK({
if ([doc[@"type"] isEqualToString:kRocketDocType])
emit(doc[@"name"], nil);
}) reduceBlock: nil version: @"1"];
}
Map/Reduce

Called on every document

Optional Reduce
Using Views in your UI
// Create a query showing rockets:
CBLLiveQuery* query = [[[database viewNamed:@"rockets"] query] asLiveQuery];
// Plug the query into the CBLUITableSource, which will use it to drive the table.
// (The CBLUITableSource uses KVO to observe the query's .rows
self.dataSource.query = query;

self.dataSource.labelProperty = @"name";
// Assumes something like this in your controller
@property (nonatomic) IBOutlet UITableView* tableView;
@property (nonatomic) IBOutlet CBLUITableSource* dataSource;
Customizing Table Cells
- (void)couchTableSource:(CBLUITableSource*)source
willUseCell:(UITableViewCell*)cell
forRow:(CBLQueryRow*)row
// Set the cell background and font:
// Configure the cell contents. Map function (above) copies the doc
properties into its value, so we can read them without having to load the
document.
NSDictionary* rowValue = row.value;

BOOL checked = [rowValue[@"check"] boolValue];
if (checked) {
cell.textLabel.textColor = [UIColor grayColor];
cell.imageView.image = [UIImage imageNamed:@"checked"];
} else {
cell.textLabel.textColor = [UIColor blackColor];
cell.imageView.image = [UIImage imageNamed: @"unchecked"];
}
// cell.textLabel.text is already set, thanks to setting up labelProperty
}
Selecting A Row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
NSLog(@"didSelectRowAtIndexPath");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row];
ASDRocket* rocket = [ASDRocket modelForDocument: row.document];
// Do something with rocket…
}
Adding Items
- (IBAction) insertNewObject: (id)sender {
ASDRocket* rocket = [ASDRocket modelForNewDocumentInDatabase:self.database];
rocket.name=name;
rocket.weight = 23.0;
NSError* error;
if (![rocket save: &error]) {
return nil;
}
NSLog(@"Rocket Created");
}
Deleting Items
-(void) tableView:(UITableView*)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete){
CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row];
ASDRocket* rocket = [ASDRocket modelForDocument: row.document];
NSError* error;
if (![rocket deleteDocument: &error]){
NSLog(@"Unable to delete Rocket");
return;
}
[self.tableView reloadData];
}
}
Replications
CBLReplication *pull;
CBLReplication *push;
h;
pull = [_database createPullReplication:_remoteURL];
pull.continuous = YES;
pull.network = @"WiFi";
push = [_database createPushReplication:_remoteURL];
push.continuous = YES;
pull.network = @"WiFi";
[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(replicationProgress:)
name:kCBLReplicationChangeNotification
push];
[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(replicationProgress:)
name:kCBLReplicationChangeNotification
pull];
CBLModel
• Maps Objects to documents
@interface ASDRocket : CBLModel
+ (NSString*) docType;
@property (strong) NSString *name;
@property (assign) double diameter;
@property (assign) double weight;
@property (assign) double coefficientFriction;
/** Returns a query for all the rockets in a database. */
+ (CBLQuery*) queryRocketsInDatabase: (CBLDatabase*)db;
/** Returns a query for all the rockets with name in a database */
+ (CBLQuery*) findInDatabase:(CBLDatabase*)db byName:(NSString *)name;
@end
CBLModel
• No types in documents
• convention is to use type field
• Map functions can pick out docs with the right type
if (doc.type == “rocket”){
emit(doc.created, doc.text)
};
Demo
• https://github.com/mwhagedorn/
couchbase_ios_rockettown
• https://github.com/mwhagedorn/
couchbase_osx_rockettown
• Two platforms synching to one database
Questions?
• @mwhagedorn

More Related Content

Couchbase Talk

  • 2. Who is this guy? • Mike Hagedorn • Language Polyglot
  • 3. Why Couchbase? Changing face of IT Demands HA Scalable Agile, Schemaless CB: Synching, Admin GUI, SDKs
  • 5. Couchbase Terms • Node • Cluster • Bucket • Document • View
  • 6. Couchbase Components Mobile embedded local db with sync Gw internet facing component Server: Ent grade nosql db
  • 8. Couchbase Lite Couchbase Lite is an embedded JSON database that can work standalone, in a P2P network, or as a remote endpoint for Couchbase Server. Embedded All IO is local Syncs are transparent in background Disconnected operation NO PUSH NO Network CBL Device 1 CBL Device 2 CB Server Cluster 1 with GW!
  • 9. Sync Gateway CBL Device 1 CBL Device 2 CB Server Cluster 1 Data Needed Here! ? Remote Data Center SGW
  • 10. Couchbase Model • An object oriented wrapper on top of CBLDocument • Somewhat like NSManagedObject
  • 11. Couchbase Challenges • Complicated Queries are Hard • Views!
  • 12. Getting Started • DL Couchbase Lite Framework • Add CouchbaseLite.framework to your project • There is no step 3
  • 13. Initialization //AppDelegate CBLManager *manager = [CBLManager sharedInstance]; NSError *error; self.database = [manager databaseNamed:kDBName error: &error]; if (error) { NSLog(@"error getting database %@",error); exit(-1); }
  • 14. Database Rockets Name Weight Diameter Cd alpha 29 25 0.75 hawk 35 30 0.8
  • 15. Document { "coefficientFriction": 0.75, "diameter": 25, "name": "alpha110", "type": "rocket", "weight": 23 } # Bb6YvfoCH7NIgsVDtgjE7O Unique ID May contain binary attachments
  • 16. Database View //RootController or CBModel //Define a view that only returns documents of type ‘kRocketDocType’ CBLView* view = [db viewNamed: @"rockets"]; if (!view.mapBlock) { // Register the map function, the first time we access the view: [view setMapBlock: MAPBLOCK({ if ([doc[@"type"] isEqualToString:kRocketDocType]) emit(doc[@"name"], nil); }) reduceBlock: nil version: @"1"]; } Map/Reduce Called on every document Optional Reduce
  • 17. Using Views in your UI // Create a query showing rockets: CBLLiveQuery* query = [[[database viewNamed:@"rockets"] query] asLiveQuery]; // Plug the query into the CBLUITableSource, which will use it to drive the table. // (The CBLUITableSource uses KVO to observe the query's .rows self.dataSource.query = query;
 self.dataSource.labelProperty = @"name"; // Assumes something like this in your controller @property (nonatomic) IBOutlet UITableView* tableView; @property (nonatomic) IBOutlet CBLUITableSource* dataSource;
  • 18. Customizing Table Cells - (void)couchTableSource:(CBLUITableSource*)source willUseCell:(UITableViewCell*)cell forRow:(CBLQueryRow*)row // Set the cell background and font: // Configure the cell contents. Map function (above) copies the doc properties into its value, so we can read them without having to load the document. NSDictionary* rowValue = row.value;
 BOOL checked = [rowValue[@"check"] boolValue]; if (checked) { cell.textLabel.textColor = [UIColor grayColor]; cell.imageView.image = [UIImage imageNamed:@"checked"]; } else { cell.textLabel.textColor = [UIColor blackColor]; cell.imageView.image = [UIImage imageNamed: @"unchecked"]; } // cell.textLabel.text is already set, thanks to setting up labelProperty }
  • 19. Selecting A Row - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"didSelectRowAtIndexPath"); NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row]; ASDRocket* rocket = [ASDRocket modelForDocument: row.document]; // Do something with rocket… }
  • 20. Adding Items - (IBAction) insertNewObject: (id)sender { ASDRocket* rocket = [ASDRocket modelForNewDocumentInDatabase:self.database]; rocket.name=name; rocket.weight = 23.0; NSError* error; if (![rocket save: &error]) { return nil; } NSLog(@"Rocket Created"); }
  • 21. Deleting Items -(void) tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ if (editingStyle == UITableViewCellEditingStyleDelete){ CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row]; ASDRocket* rocket = [ASDRocket modelForDocument: row.document]; NSError* error; if (![rocket deleteDocument: &error]){ NSLog(@"Unable to delete Rocket"); return; } [self.tableView reloadData]; } }
  • 22. Replications CBLReplication *pull; CBLReplication *push; h; pull = [_database createPullReplication:_remoteURL]; pull.continuous = YES; pull.network = @"WiFi"; push = [_database createPushReplication:_remoteURL]; push.continuous = YES; pull.network = @"WiFi"; [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(replicationProgress:) name:kCBLReplicationChangeNotification push]; [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(replicationProgress:) name:kCBLReplicationChangeNotification pull];
  • 23. CBLModel • Maps Objects to documents @interface ASDRocket : CBLModel + (NSString*) docType; @property (strong) NSString *name; @property (assign) double diameter; @property (assign) double weight; @property (assign) double coefficientFriction; /** Returns a query for all the rockets in a database. */ + (CBLQuery*) queryRocketsInDatabase: (CBLDatabase*)db; /** Returns a query for all the rockets with name in a database */ + (CBLQuery*) findInDatabase:(CBLDatabase*)db byName:(NSString *)name; @end
  • 24. CBLModel • No types in documents • convention is to use type field • Map functions can pick out docs with the right type if (doc.type == “rocket”){ emit(doc.created, doc.text) };