Beginning iClouddevelopmentRocchi Cesare    @_funkyboy   studiomagnolia.com
Outline What is iCloud? How does it work? Are there alternatives?
Who am I?
UX designer and developer
mnml
< is >
execution matters
lean approach
1000 details coming together
Giveaway
1 of the Wenderlich’s                raywenderlich.com
ARC                     GameCenter API           Storyboards                            News Stand  iCloudTurn Based Gamin...
twitter.com/_funkyboycesare@studiomagnolia.com
Giveaway
Giveaway(yes, another)
www.icloudfordevelopers.com
UIDocument                              Key-Value store ConflictResolution                                       CoreData  ...
twitter.com/_funkyboycesare@studiomagnolia.com     www.icloudfordevelopers.com
Who are you?
What is iCloud?
6028 Startown Rd, Maiden, NC
Stores and synchs stuff
It just works ...
... when it works
Seamlessness can be a limit
Pros (for devs) No server setup No costs No rumination on synch
Cons (for devs) Stick to a synch model No http API No control on upload
Pros and Cons for usersExpectation
Under the hood
DaemonMonitors changesWorks on metadataShreds files
Special folder, synched
Synched when “appropriate”
AppropriateWhich OS?Which connection?Battery status?
Placeholders
Information Structure Document Key-value CoreData
UIDocument
UIDocumentNSFilePresenterNon-blocking read/write
-(void) openWithCompletionHandler:^(BOOL success) { }
- (BOOL)loadFromContents:(id)contents                  ofType:(NSString *)typeName                   error:(NSError **)out...
@interface SMNote : UIDocument
@implementation SMNote- (BOOL)loadFromContents:(id)contents                  ofType:(NSString *)typeName                  ...
- (BOOL) saveToURL:(NSURL *)url  forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) { }
- (id)contentsForType:(NSString *)typeName                error:(NSError **)outError {}
- (id)contentsForType:(NSString *)typeName                error:(NSError **)outError {    return [NSData dataWithBytes:[se...
AutosaveupdateChangeCount:use the methods of the undoManager
@implementation SMNote@synthesize noteContent;// Called whenever the application reads data- (BOOL)loadFromContents:(id)co...
Opening a document
Opening a documentBuild and run a queryWait for resultsUnfold results
#import "SMNote.h"@interface SMAppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *wi...
NSMetadataQuery
- (void)loadDocument {    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];    _query = query;    [query setSearchS...
- (void)loadDocument {    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];    _query = query;    [query setSearchS...
- (void)loadDocument {    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];    _query = query;    [query setSearchS...
NSPredicate *pred = [NSPredicate predicateWithFormat:                                    @"%K like Note_*",               ...
Asynchronous!
- (void)queryDidFinish:(NSNotification *)notification {    NSMetadataQuery *query = [notification object];    [query disab...
- (void)loadData:(NSMetadataQuery *)query {    if ([query resultCount] == 1) {        NSMetadataItem *item = [query result...
- (void)loadData:(NSMetadataQuery *)query {    if ([query resultCount] == 1) {        NSMetadataItem *item = [query result...
else {    NSURL *ubiq = [[NSFileManager defaultManager]                    URLForUbiquityContainerIdentifier:nil];    NSUR...
else {     NSURL *ubiq = [[NSFileManager defaultManager]                     URLForUbiquityContainerIdentifier:nil];     N...
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    ...    [s...
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    ...    [s...
- (void)viewDidLoad {    [super viewDidLoad];    [[NSNotificationCenter defaultCenter]                     addObserver:sel...
Switching on/off
- (NSURL *) localNotesURL {    return [[[NSFileManager defaultManager]             URLsForDirectory:NSDocumentDirectory   ...
- (void) setNoteUbiquity {    NSURL *baseUrl = [self localNotesURL];    if (_useiCloud)        baseUrl = [self ubiquitousN...
- (void) startMigration {    NSOperationQueue *iCloudQueue = [NSOperationQueue new];    NSInvocationOperation *op =       ...
Custom documents
SMNotesDocument  SMNote      SMNote   SMNote                                ...
@interface SMNote : NSObject <NSCoding>@property   (copy, nonatomic) NSString   *noteId;@property   (copy, nonatomic) NSSt...
#import "SMNote.h"@interface SMNotesDocument : UIDocument@property (nonatomic, strong) NSMutableArray *entries;@property (...
#import "SMNote.h"@interface SMNotesDocument : UIDocument@property (nonatomic, strong) NSMutableArray *entries;@property (...
- (id)contentsForType:(NSString *)typeName                error:(NSError **)outError {    NSMutableDictionary *w = [NSMuta...
- (id)contentsForType:(NSString *)typeName                error:(NSError **)outError {    NSMutableDictionary *w = [NSMuta...
- (BOOL)loadFromContents:(id)contents                  ofType:(NSString *)typeName                   error:(NSError **)out...
- (BOOL)loadFromContents:(id)contents                  ofType:(NSString *)typeName                   error:(NSError **)out...
Uniform Type Identifier
Key-value
Key-value   1Mb
Key-value    1Mb was 64Kb !
- (void) saveNoteAsCurrent {    [[NSUbiquitousKeyValueStore defaultStore]               setString:self.currentNote.noteId ...
- (void) saveNoteAsCurrent {      [[NSUbiquitousKeyValueStore defaultStore]                 setString:self.currentNote.not...
NSUbiquitousKeyValueStore* store =    [NSUbiquitousKeyValueStore defaultStore];[[NSNotificationCenter defaultCenter] addOb...
Conflict Resolution
Conflict ResolutionUp to the devdocumentState
DocumentStatesUIDocumentStateNormalUIDocumentStateClosedUIDocumentStateInConflictUIDocumentStateSavingErrorUIDocumentState...
UIDocumentStateChangedNotification
[[NSNotificationCenter defaultCenter]                   addObserver:self                      selector:@selector(noteHasCh...
UIDocumentState s = [n documentState];switch (s) {    case UIDocumentStateNormal:        NSLog(@"Everything is fine");    ...
UI conflict      vsiCloud conflict
Resolution policy last wins prompt user automatic merge
Resolution policy last wins prompt user automatic merge NSFileVersion
NSError *err;NSURL *url = [[NSFileManager defaultManager]   URLForPublishingUbiquitousItemAtURL:[self.currentNote fileURL]...
Tips & Tricks
Patience!
Test on wireless & 3G
Regenerate provisioning
Delete previous data
Restart device
API throttle!
App policyBe gentle with storage<App_home>/tmp<App_home>/Library/Caches/
App policyDocuments is backed upmark files as “do not backup”
// iOS 5.0.1#import <sys/xattr.h>- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {    const char* filePath = [[URL ...
// iOS 5.1- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {    NSError *error = nil;    BOOL success = [URL setReso...
“To iCloud or not to iCloud?”
Alternatives
Alternatives dropbox parse.com cloudmine stackmob custom
Dropboxdocumentsauthenticationno notifications
Dropboxother platformsno CR (revision #)expectation
Parse
ParseORM approachRecently releasedNo cost of infrastructure
ParsePay as you useLimit of calls/mo
PFObject *note = [PFObject objectWithClassName:@"Note"];[note setObject:@"Ciao"         forKey:@"title"];[note setObject:@...
[note saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error){    if (error) {          NSLog(@"Note not saved");     ...
ParseOther platformsREST APIPush notificationsObject browser
curl -X POST -H "X-Parse-Application-Id: ${APPLICATION_ID}" -H "X-Parse-REST-API-Key: ${REST_API_KEY}" -H "Content-Type: a...
PFObject *note = [PFObject objectWithClassName:@"Note"];[note setObject:@"Ciao"           forKey:@"title"];[note setObject...
RecapUIDocumentKey-Value storeAlternatives
“You can’t always get what           you wantbut if you try sometime, you      just might find ...”
“You can’t always get what           you wantbut if you try sometime, you      just might find ...”                      Ro...
Contacttwitter.com/_funkyboycesare@studiomagnolia.comhttp://studiomagnolia.com
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
×

Beginning icloud development - Cesare Rocchi - WhyMCA

2,166 views

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
2,166
On SlideShare
0
From Embeds
0
Number of Embeds
72
Actions
Shares
0
Downloads
28
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Beginning icloud development - Cesare Rocchi - WhyMCA

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

×