129
Beginning iCloud development Rocchi Cesare @_funkyboy studiomagnolia.com

Beginning icloud development - Cesare Rocchi - WhyMCA

  • Upload
    whymca

  • View
    1.502

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Beginning icloud development - Cesare Rocchi - WhyMCA

Beginning iCloud developmentRocchi Cesare

@_funkyboy studiomagnolia.com

Page 2: Beginning icloud development - Cesare Rocchi - WhyMCA

Outline

What is iCloud?

How does it work?

Are there alternatives?

Page 3: Beginning icloud development - Cesare Rocchi - WhyMCA

Who am I?

Page 4: Beginning icloud development - Cesare Rocchi - WhyMCA

UX designer and developer

Page 5: Beginning icloud development - Cesare Rocchi - WhyMCA

mnml

Page 6: Beginning icloud development - Cesare Rocchi - WhyMCA

< is >

Page 7: Beginning icloud development - Cesare Rocchi - WhyMCA

execution matters

Page 8: Beginning icloud development - Cesare Rocchi - WhyMCA

lean approach

Page 9: Beginning icloud development - Cesare Rocchi - WhyMCA

1000 details coming together

Page 10: Beginning icloud development - Cesare Rocchi - WhyMCA

Giveaway

Page 11: Beginning icloud development - Cesare Rocchi - WhyMCA

1 of the Wenderlich’s

raywenderlich.com

Page 12: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 13: Beginning icloud development - Cesare Rocchi - WhyMCA

iCloud

Storyboards

ARC

OpenGL ES 2.0

News Stand

Turn Based Gaming

GameCenter API

Page 15: Beginning icloud development - Cesare Rocchi - WhyMCA

Giveaway

Page 16: Beginning icloud development - Cesare Rocchi - WhyMCA

Giveaway(yes, another)

Page 18: Beginning icloud development - Cesare Rocchi - WhyMCA

www.icloudfordevelopers.com

Conflict Resolution

CoreData

UIDocument

Key-Value store

Custom Documents

Page 20: Beginning icloud development - Cesare Rocchi - WhyMCA

Who are you?

Page 21: Beginning icloud development - Cesare Rocchi - WhyMCA

What is iCloud?

Page 22: Beginning icloud development - Cesare Rocchi - WhyMCA

6028 Startown Rd, Maiden, NC

Page 23: Beginning icloud development - Cesare Rocchi - WhyMCA

Stores and synchs stuff

Page 24: Beginning icloud development - Cesare Rocchi - WhyMCA

It just works ...

Page 25: Beginning icloud development - Cesare Rocchi - WhyMCA

... when it works

Page 26: Beginning icloud development - Cesare Rocchi - WhyMCA

Seamlessness can be a limit

Page 27: Beginning icloud development - Cesare Rocchi - WhyMCA

Pros (for devs)

No server setup

No costs

No rumination on synch

Page 28: Beginning icloud development - Cesare Rocchi - WhyMCA

Cons (for devs)

Stick to a synch model

No http API

No control on upload

Page 29: Beginning icloud development - Cesare Rocchi - WhyMCA

Pros and Cons for users

Expectation

Page 30: Beginning icloud development - Cesare Rocchi - WhyMCA

Under the hood

Page 31: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 32: Beginning icloud development - Cesare Rocchi - WhyMCA

Daemon

Monitors changes

Works on metadata

Shreds files

Page 33: Beginning icloud development - Cesare Rocchi - WhyMCA

Special folder, synched

Page 34: Beginning icloud development - Cesare Rocchi - WhyMCA

Synched when “appropriate”

Page 35: Beginning icloud development - Cesare Rocchi - WhyMCA

Appropriate

Which OS?

Which connection?

Battery status?

Page 36: Beginning icloud development - Cesare Rocchi - WhyMCA

Placeholders

Page 37: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 38: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 39: Beginning icloud development - Cesare Rocchi - WhyMCA

Information Structure

Document

Key-value

CoreData

Page 40: Beginning icloud development - Cesare Rocchi - WhyMCA

UIDocument

Page 41: Beginning icloud development - Cesare Rocchi - WhyMCA

UIDocument

NSFilePresenter

Non-blocking read/write

Page 42: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 43: Beginning icloud development - Cesare Rocchi - WhyMCA

-(void) openWithCompletionHandler:^(BOOL success) { }

Page 44: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { }

Page 45: Beginning icloud development - Cesare Rocchi - WhyMCA

@interface SMNote : UIDocument

Page 46: Beginning icloud development - Cesare Rocchi - WhyMCA

@implementation SMNote

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError {

if ([contents length] > 0) { self.myContent = [[NSString alloc] initWithBytes:[contents bytes] length:[contents length] encoding:NSUTF8StringEncoding]; } else {

// Default content self.myContent = @"Empty";

} return YES; }

Page 47: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL) saveToURL:(NSURL *)url forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) { }

Page 48: Beginning icloud development - Cesare Rocchi - WhyMCA

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError {}

Page 49: Beginning icloud development - Cesare Rocchi - WhyMCA

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError { return [NSData dataWithBytes:[self.myContent UTF8String] length:[self.myContent length]];

}

Page 50: Beginning icloud development - Cesare Rocchi - WhyMCA

Autosave

updateChangeCount:

use the methods of the undoManager

Page 51: Beginning icloud development - Cesare Rocchi - WhyMCA

@implementation SMNote

@synthesize noteContent;

// Called whenever the application reads data - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { }

// Called whenever the application (auto)saves the content - (id)contentsForType:(NSString *)typeName error:(NSError **)outError { }

Page 52: Beginning icloud development - Cesare Rocchi - WhyMCA

Opening a document

Page 53: Beginning icloud development - Cesare Rocchi - WhyMCA

Opening a document

Build and run a query

Wait for results

Unfold results

Page 54: Beginning icloud development - Cesare Rocchi - WhyMCA

#import "SMNote.h"

@interface SMAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;@property (strong, nonatomic) SMViewController *viewController;

@property (strong) SMNote *doc;@property (strong) NSMetadataQuery *query;

- (void)loadDocument;

@end

Page 55: Beginning icloud development - Cesare Rocchi - WhyMCA

NSMetadataQuery

Page 56: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query;

[query setSearchScopes:[NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]]; }

Page 57: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query;

[query setSearchScopes:[NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]];

NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@",

NSMetadataItemFSNameKey, kFILENAME];

[query setPredicate:pred]; }

Page 58: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query;

[query setSearchScopes:[NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]];

NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@",

NSMetadataItemFSNameKey, kFILENAME];

[query setPredicate:pred];

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(queryDidFinish:) name:NSMetadataQueryDidFinishGatheringNotification

object:query]; [query startQuery]; }

Page 59: Beginning icloud development - Cesare Rocchi - WhyMCA

NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K like 'Note_*'", NSMetadataItemFSNameKey];

Page 60: Beginning icloud development - Cesare Rocchi - WhyMCA

Asynchronous!

Page 61: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)queryDidFinish:(NSNotification *)notification { NSMetadataQuery *query = [notification object]; [query disableUpdates]; [query stopQuery]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query]; _query = nil; ! [self loadData:query]; }

Page 62: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)loadData:(NSMetadataQuery *)query { if ([query resultCount] == 1) {

NSMetadataItem *item = [query resultAtIndex:0]; NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

SMNote *doc = [[SMNote alloc] initWithFileURL:url];

}

}

Page 63: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)loadData:(NSMetadataQuery *)query { if ([query resultCount] == 1) {

NSMetadataItem *item = [query resultAtIndex:0]; NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

self.doc = [[SMNote alloc] initWithFileURL:url];

[self.doc openWithCompletionHandler:^(BOOL success) {

if (success) { NSLog(@"iCloud document opened"); } else { NSLog(@"failed opening document from iCloud"); } }];

}

}

Page 64: Beginning icloud development - Cesare Rocchi - WhyMCA

else { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent: @"Documents"]

URLByAppendingPathComponent:kFILENAME]; SMNote *doc = [[SMNote alloc] initWithFileURL:ubiquitousPackage]; }

Page 65: Beginning icloud development - Cesare Rocchi - WhyMCA

else { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent: @"Documents"]

URLByAppendingPathComponent:kFILENAME]; SMNote *doc = [[SMNote alloc] initWithFileURL:ubiquitousPackage]; self.doc = doc; [doc saveToURL: [doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {

if (success) { [doc openWithCompletionHandler:^(BOOL success) { NSLog(@"new document opened from iCloud"); }]; } }];

}

Page 66: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

... [self.window makeKeyAndVisible]; NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

if (ubiq) {

NSLog(@"iCloud access at %@", ubiq); [self loadDocument];

} else {

NSLog(@"No iCloud access");

} return YES;}

Page 67: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

... [self.window makeKeyAndVisible]; NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

if (ubiq) {

NSLog(@"iCloud access at %@", ubiq); [self loadDocument];

} else {

NSLog(@"No iCloud access");

} return YES;}

Page 68: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void)viewDidLoad {

[super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataReloaded:) name:@"noteModified"

object:nil];}

- (void)dataReloaded:(NSNotification *)notification { self.doc = notification.object; self.noteView.text = self.doc.noteContent; }

Page 69: Beginning icloud development - Cesare Rocchi - WhyMCA

Switching on/off

Page 70: Beginning icloud development - Cesare Rocchi - WhyMCA

- (NSURL *) localNotesURL { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; }

- (NSURL *) ubiquitousNotesURL { return [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@"Documents"]; }

Page 71: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void) setNoteUbiquity { NSURL *baseUrl = [self localNotesURL]; if (_useiCloud) baseUrl = [self ubiquitousNotesURL]; NSURL *destUrl = [baseUrl URLByAppendingPathComponent: [note.fileURL lastPathComponent]];

[[NSFileManager defaultManager] setUbiquitous:_useiCloud itemAtURL:note.fileURL destinationURL:destUrl error:NULL]; }

Don’t call it on the main thread!

Page 72: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void) startMigration {

NSOperationQueue *iCloudQueue = [NSOperationQueue new]; NSInvocationOperation *op =

[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(setNoteUbiquity) object:nil];

[iCloudQueue addOperation:op]; }

Page 73: Beginning icloud development - Cesare Rocchi - WhyMCA

Custom documents

Page 74: Beginning icloud development - Cesare Rocchi - WhyMCA

SMNotesDocument

SMNote SMNote SMNote

...

Page 75: Beginning icloud development - Cesare Rocchi - WhyMCA

@interface SMNote : NSObject <NSCoding>

@property (copy, nonatomic) NSString *noteId;@property (copy, nonatomic) NSString *noteContent;@property (strong, nonatomic) NSDate *createdAt;@property (strong, nonatomic) NSDate *updatedAt;

@end

Page 76: Beginning icloud development - Cesare Rocchi - WhyMCA

#import "SMNote.h"

@interface SMNotesDocument : UIDocument

@property (nonatomic, strong) NSMutableArray *entries;@property (nonatomic, strong) NSFileWrapper *fileWrapper;

@end

Page 77: Beginning icloud development - Cesare Rocchi - WhyMCA

#import "SMNote.h"

@interface SMNotesDocument : UIDocument

@property (nonatomic, strong) NSMutableArray *entries;@property (nonatomic, strong) NSFileWrapper *fileWrapper;

@end

Page 78: Beginning icloud development - Cesare Rocchi - WhyMCA

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError {

NSMutableDictionary *w = [NSMutableDictionary dictionary]; NSMutableData *data = [NSMutableData data]; NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; [arch encodeObject:_entries forKey:@"entries"]; [arch finishEncoding]; }

Page 79: Beginning icloud development - Cesare Rocchi - WhyMCA

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError {

NSMutableDictionary *w = [NSMutableDictionary dictionary]; NSMutableData *data = [NSMutableData data]; NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; [arch encodeObject:_entries forKey:@"entries"]; [arch finishEncoding]; NSFileWrapper *entriesWrapper = [[NSFileWrapper alloc]

initRegularFileWithContents:data]; [w setObject:entriesWrapper forKey:@"notes.dat"]; // add other wrappers if you like NSFileWrapper *res = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:w]; return res; }

Page 80: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { NSFileWrapper *wrapper = (NSFileWrapper *)contents; NSDictionary *d = [wrapper fileWrappers]; NSFileWrapper *entriesWrap = [d objectForKey:@"notes.dat"]; }

Page 81: Beginning icloud development - Cesare Rocchi - WhyMCA

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { NSFileWrapper *wrapper = (NSFileWrapper *)contents; NSDictionary *d = [wrapper fileWrappers]; NSFileWrapper *entriesWrap = [d objectForKey:@"notes.dat"]; NSData *data = [entriesWrap regularFileContents]; NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; _entries = [arch decodeObjectForKey:@"entries"]; // Notify the view

}

Page 82: Beginning icloud development - Cesare Rocchi - WhyMCA

Uniform Type Identifier

Page 83: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 84: Beginning icloud development - Cesare Rocchi - WhyMCA

Key-value

Page 85: Beginning icloud development - Cesare Rocchi - WhyMCA

Key-value1Mb

Page 86: Beginning icloud development - Cesare Rocchi - WhyMCA

Key-value1Mb

was 64Kb !

Page 87: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void) saveNoteAsCurrent {

[[NSUbiquitousKeyValueStore defaultStore] setString:self.currentNote.noteId forKey:@"com.studiomagnolia.currentNote"];

[[NSUbiquitousKeyValueStore defaultStore] synchronize];

}

Page 88: Beginning icloud development - Cesare Rocchi - WhyMCA

- (void) saveNoteAsCurrent {

[[NSUbiquitousKeyValueStore defaultStore] setString:self.currentNote.noteId forKey:@"com.studiomagnolia.currentNote"];

[[NSUbiquitousKeyValueStore defaultStore] synchronize];

}

NSString *currentNoteId = [[NSUbiquitousKeyValueStore defaultStore] stringForKey: @"com.studiomagnolia.currentNote"];

Page 89: Beginning icloud development - Cesare Rocchi - WhyMCA

NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateCurrentNoteIfNeeded:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:store];

[store synchronize];

Page 90: Beginning icloud development - Cesare Rocchi - WhyMCA

Conflict Resolution

Page 91: Beginning icloud development - Cesare Rocchi - WhyMCA

Conflict Resolution

Up to the dev

documentState

Page 92: Beginning icloud development - Cesare Rocchi - WhyMCA

DocumentStates

UIDocumentStateNormal

UIDocumentStateClosed

UIDocumentStateInConflict

UIDocumentStateSavingError

UIDocumentStateEditingDisabled

Page 93: Beginning icloud development - Cesare Rocchi - WhyMCA

UIDocumentStateChangedNotification

Page 94: Beginning icloud development - Cesare Rocchi - WhyMCA

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noteHasChanged:) name:UIDocumentStateChangedNotification object:nil];

Page 95: Beginning icloud development - Cesare Rocchi - WhyMCA

UIDocumentState s = [n documentState]; switch (s) {

case UIDocumentStateNormal: NSLog(@"Everything is fine"); break;

case UIDocumentStateInConflict: NSLog(@"There is a conflict"); break;

...

default: NSLog(@"Unknown state"); break;

}

Page 96: Beginning icloud development - Cesare Rocchi - WhyMCA

UI conflict vs

iCloud conflict

Page 97: Beginning icloud development - Cesare Rocchi - WhyMCA

Resolution policy

last wins

prompt user

automatic merge

Page 98: Beginning icloud development - Cesare Rocchi - WhyMCA

Resolution policy

last wins

prompt user

automatic merge

NSFileVersion

Page 99: Beginning icloud development - Cesare Rocchi - WhyMCA

NSError *err; NSURL *url = [[NSFileManager defaultManager] URLForPublishingUbiquitousItemAtURL:[self.currentNote fileURL] expirationDate:&expirationInOneHourSinceNow error:&err];

Page 100: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 101: Beginning icloud development - Cesare Rocchi - WhyMCA

Tips & Tricks

Page 102: Beginning icloud development - Cesare Rocchi - WhyMCA

Patience!

Page 103: Beginning icloud development - Cesare Rocchi - WhyMCA

Test on wireless & 3G

Page 104: Beginning icloud development - Cesare Rocchi - WhyMCA

Regenerate provisioning

Page 105: Beginning icloud development - Cesare Rocchi - WhyMCA

Delete previous data

Page 106: Beginning icloud development - Cesare Rocchi - WhyMCA
Page 107: Beginning icloud development - Cesare Rocchi - WhyMCA

Restart device

Page 108: Beginning icloud development - Cesare Rocchi - WhyMCA

API throttle!

Page 109: Beginning icloud development - Cesare Rocchi - WhyMCA

App policy

Be gentle with storage

<App_home>/tmp

<App_home>/Library/Caches/

Page 110: Beginning icloud development - Cesare Rocchi - WhyMCA

App policy

Documents is backed up

mark files as “do not backup”

Page 111: Beginning icloud development - Cesare Rocchi - WhyMCA

// iOS 5.0.1

#import <sys/xattr.h>

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL { const char* filePath = [[URL path] fileSystemRepresentation]; const char* attrName = "com.apple.MobileBackup"; u_int8_t attrValue = 1; int result = setxattr(filePath, attrName, &attrValue,

sizeof(attrValue), 0, 0); return result == 0;

}

Page 112: Beginning icloud development - Cesare Rocchi - WhyMCA

// iOS 5.1

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL { NSError *error = nil;

BOOL success = [URL setResourceValue: [NSNumber numberWithBool:YES] forKey: NSURLIsExcludedFromBackupKey

error: &error]; if(!success){

NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);

}

return success;}

Page 113: Beginning icloud development - Cesare Rocchi - WhyMCA

“To iCloud or not to iCloud?”

Page 114: Beginning icloud development - Cesare Rocchi - WhyMCA

Alternatives

Page 115: Beginning icloud development - Cesare Rocchi - WhyMCA

Alternatives

dropbox

parse.com

cloudmine

stackmob

custom

Page 116: Beginning icloud development - Cesare Rocchi - WhyMCA

Dropbox

documents

authentication

no notifications

Page 117: Beginning icloud development - Cesare Rocchi - WhyMCA

Dropbox

other platforms

no CR (revision #)

expectation

Page 118: Beginning icloud development - Cesare Rocchi - WhyMCA

Parse

Page 119: Beginning icloud development - Cesare Rocchi - WhyMCA

Parse

ORM approach

Recently released

No cost of infrastructure

Page 120: Beginning icloud development - Cesare Rocchi - WhyMCA

Parse

Pay as you use

Limit of calls/mo

Page 121: Beginning icloud development - Cesare Rocchi - WhyMCA

PFObject *note = [PFObject objectWithClassName:@"Note"];

[note setObject:@"Ciao" forKey:@"title"];

[note setObject:@"Note on Parse" forKey:@"content"];

[note save];//[note saveInBackground];//[note saveEventually];

Page 122: Beginning icloud development - Cesare Rocchi - WhyMCA

[note saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { if (error) {

NSLog(@"Note not saved");

} else {

NSLog(@"Note saved successfully");

}}];

Page 123: Beginning icloud development - Cesare Rocchi - WhyMCA

Parse

Other platforms

REST API

Push notifications

Object browser

Page 124: Beginning icloud development - Cesare Rocchi - WhyMCA

curl -X POST \-H "X-Parse-Application-Id: ${APPLICATION_ID}" \-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \-H "Content-Type: application/json" \-d '{"note": 001, "title": "Ciao", "content": “Note on parse” }' \https://api.parse.com/1/classes/GameScore

Page 125: Beginning icloud development - Cesare Rocchi - WhyMCA

PFObject *note = [PFObject objectWithClassName:@"Note"];

[note setObject:@"Ciao" forKey:@"title"];

[note setObject:@"Note on parse" forKey:@"content"];

PFObject *myTag = [PFObject objectWithClassName:@"Tag"];

[myTag setObject:@"important" forKey:@"tagName"];

// Add a relation[note setObject:myTag forKey:@"tag"];

// Saves both[note saveInBackground];

Page 126: Beginning icloud development - Cesare Rocchi - WhyMCA

Recap

UIDocument

Key-Value store

Alternatives

Page 127: Beginning icloud development - Cesare Rocchi - WhyMCA

“You can’t always get what you want

but if you try sometime, you just might find ...”

Page 128: Beginning icloud development - Cesare Rocchi - WhyMCA

“You can’t always get what you want

but if you try sometime, you just might find ...”

Rolling Stones

Page 129: Beginning icloud development - Cesare Rocchi - WhyMCA

Contact

twitter.com/_funkyboy

[email protected]

http://studiomagnolia.com