Your SlideShare is downloading. ×
0
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Beginning icloud development - Cesare Rocchi - WhyMCA

1,518

Published on

Published in: Technology, Design
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,518
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
27
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Beginning iClouddevelopmentRocchi Cesare @_funkyboy studiomagnolia.com
  • 2. Outline What is iCloud? How does it work? Are there alternatives?
  • 3. Who am I?
  • 4. UX designer and developer
  • 5. mnml
  • 6. < is >
  • 7. execution matters
  • 8. lean approach
  • 9. 1000 details coming together
  • 10. Giveaway
  • 11. 1 of the Wenderlich’s raywenderlich.com
  • 12. ARC GameCenter API Storyboards News Stand iCloudTurn Based Gaming OpenGL ES 2.0
  • 13. twitter.com/_funkyboycesare@studiomagnolia.com
  • 14. Giveaway
  • 15. Giveaway(yes, another)
  • 16. www.icloudfordevelopers.com
  • 17. UIDocument Key-Value store ConflictResolution CoreData Custom Documents www.icloudfordevelopers.com
  • 18. twitter.com/_funkyboycesare@studiomagnolia.com www.icloudfordevelopers.com
  • 19. Who are you?
  • 20. What is iCloud?
  • 21. 6028 Startown Rd, Maiden, NC
  • 22. Stores and synchs stuff
  • 23. It just works ...
  • 24. ... when it works
  • 25. Seamlessness can be a limit
  • 26. Pros (for devs) No server setup No costs No rumination on synch
  • 27. Cons (for devs) Stick to a synch model No http API No control on upload
  • 28. Pros and Cons for usersExpectation
  • 29. Under the hood
  • 30. DaemonMonitors changesWorks on metadataShreds files
  • 31. Special folder, synched
  • 32. Synched when “appropriate”
  • 33. AppropriateWhich OS?Which connection?Battery status?
  • 34. Placeholders
  • 35. Information Structure Document Key-value CoreData
  • 36. UIDocument
  • 37. UIDocumentNSFilePresenterNon-blocking read/write
  • 38. -(void) openWithCompletionHandler:^(BOOL success) { }
  • 39. - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { }
  • 40. @interface SMNote : UIDocument
  • 41. @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;}
  • 42. - (BOOL) saveToURL:(NSURL *)url forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) { }
  • 43. - (id)contentsForType:(NSString *)typeName error:(NSError **)outError {}
  • 44. - (id)contentsForType:(NSString *)typeName error:(NSError **)outError { return [NSData dataWithBytes:[self.myContent UTF8String] length:[self.myContent length]];}
  • 45. AutosaveupdateChangeCount:use the methods of the undoManager
  • 46. @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 {}
  • 47. Opening a document
  • 48. Opening a documentBuild and run a queryWait for resultsUnfold results
  • 49. #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
  • 50. NSMetadataQuery
  • 51. - (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query; [query setSearchScopes:[NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]];}
  • 52. - (void)loadDocument { NSMetadataQuery *query = [[NSMetadataQuery alloc] init]; _query = query; [query setSearchScopes:[NSArray arrayWithObject: NSMetadataQueryUbiquitousDocumentsScope]]; NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, kFILENAME]; [query setPredicate:pred];}
  • 53. - (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];}
  • 54. NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K like Note_*", NSMetadataItemFSNameKey];
  • 55. Asynchronous!
  • 56. - (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];}
  • 57. - (void)loadData:(NSMetadataQuery *)query { if ([query resultCount] == 1) { NSMetadataItem *item = [query resultAtIndex:0]; NSURL *url = [item valueForAttribute:NSMetadataItemURLKey]; SMNote *doc = [[SMNote alloc] initWithFileURL:url]; }}
  • 58. - (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"); } }]; }}
  • 59. else { NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent: @"Documents"] URLByAppendingPathComponent:kFILENAME]; SMNote *doc = [[SMNote alloc] initWithFileURL:ubiquitousPackage];}
  • 60. 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:UIDocumentSaveForCreatingcompletionHandler:^(BOOL success) { if (success) { [doc openWithCompletionHandler:^(BOOL success) { NSLog(@"new document opened from iCloud"); }]; } }]; }
  • 61. - (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(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;}
  • 62. - (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(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;}
  • 63. - (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;}
  • 64. Switching on/off
  • 65. - (NSURL *) localNotesURL { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}- (NSURL *) ubiquitousNotesURL { return [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:@"Documents"];}
  • 66. - (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!
  • 67. - (void) startMigration { NSOperationQueue *iCloudQueue = [NSOperationQueue new]; NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(setNoteUbiquity) object:nil]; [iCloudQueue addOperation:op];}
  • 68. Custom documents
  • 69. SMNotesDocument SMNote SMNote SMNote ...
  • 70. @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
  • 71. #import "SMNote.h"@interface SMNotesDocument : UIDocument@property (nonatomic, strong) NSMutableArray *entries;@property (nonatomic, strong) NSFileWrapper *fileWrapper;@end
  • 72. #import "SMNote.h"@interface SMNotesDocument : UIDocument@property (nonatomic, strong) NSMutableArray *entries;@property (nonatomic, strong) NSFileWrapper *fileWrapper;@end
  • 73. - (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];}
  • 74. - (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;}
  • 75. - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError { NSFileWrapper *wrapper = (NSFileWrapper *)contents; NSDictionary *d = [wrapper fileWrappers]; NSFileWrapper *entriesWrap = [d objectForKey:@"notes.dat"];}
  • 76. - (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}
  • 77. Uniform Type Identifier
  • 78. Key-value
  • 79. Key-value 1Mb
  • 80. Key-value 1Mb was 64Kb !
  • 81. - (void) saveNoteAsCurrent { [[NSUbiquitousKeyValueStore defaultStore] setString:self.currentNote.noteId forKey:@"com.studiomagnolia.currentNote"]; [[NSUbiquitousKeyValueStore defaultStore] synchronize];}
  • 82. - (void) saveNoteAsCurrent { [[NSUbiquitousKeyValueStore defaultStore] setString:self.currentNote.noteId forKey:@"com.studiomagnolia.currentNote"]; [[NSUbiquitousKeyValueStore defaultStore] synchronize];} NSString *currentNoteId = [[NSUbiquitousKeyValueStore defaultStore] stringForKey: @"com.studiomagnolia.currentNote"];
  • 83. NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateCurrentNoteIfNeeded:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:store];[store synchronize];
  • 84. Conflict Resolution
  • 85. Conflict ResolutionUp to the devdocumentState
  • 86. DocumentStatesUIDocumentStateNormalUIDocumentStateClosedUIDocumentStateInConflictUIDocumentStateSavingErrorUIDocumentStateEditingDisabled
  • 87. UIDocumentStateChangedNotification
  • 88. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noteHasChanged:) name:UIDocumentStateChangedNotification object:nil];
  • 89. 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;}
  • 90. UI conflict vsiCloud conflict
  • 91. Resolution policy last wins prompt user automatic merge
  • 92. Resolution policy last wins prompt user automatic merge NSFileVersion
  • 93. NSError *err;NSURL *url = [[NSFileManager defaultManager] URLForPublishingUbiquitousItemAtURL:[self.currentNote fileURL] expirationDate:&expirationInOneHourSinceNow error:&err];
  • 94. Tips & Tricks
  • 95. Patience!
  • 96. Test on wireless & 3G
  • 97. Regenerate provisioning
  • 98. Delete previous data
  • 99. Restart device
  • 100. API throttle!
  • 101. App policyBe gentle with storage<App_home>/tmp<App_home>/Library/Caches/
  • 102. App policyDocuments is backed upmark files as “do not backup”
  • 103. // 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;}
  • 104. // 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;}
  • 105. “To iCloud or not to iCloud?”
  • 106. Alternatives
  • 107. Alternatives dropbox parse.com cloudmine stackmob custom
  • 108. Dropboxdocumentsauthenticationno notifications
  • 109. Dropboxother platformsno CR (revision #)expectation
  • 110. Parse
  • 111. ParseORM approachRecently releasedNo cost of infrastructure
  • 112. ParsePay as you useLimit of calls/mo
  • 113. PFObject *note = [PFObject objectWithClassName:@"Note"];[note setObject:@"Ciao" forKey:@"title"];[note setObject:@"Note on Parse" forKey:@"content"];[note save];//[note saveInBackground];//[note saveEventually];
  • 114. [note saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error){ if (error) { NSLog(@"Note not saved"); } else { NSLog(@"Note saved successfully"); }}];
  • 115. ParseOther platformsREST APIPush notificationsObject browser
  • 116. 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
  • 117. 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];
  • 118. RecapUIDocumentKey-Value storeAlternatives
  • 119. “You can’t always get what you wantbut if you try sometime, you just might find ...”
  • 120. “You can’t always get what you wantbut if you try sometime, you just might find ...” Rolling Stones
  • 121. Contacttwitter.com/_funkyboycesare@studiomagnolia.comhttp://studiomagnolia.com

×