integrating core data and cloudkit
play

Integrating Core Data and CloudKit Jared Sorge Scorebook Remember - PowerPoint PPT Presentation

Integrating Core Data and CloudKit Jared Sorge Scorebook Remember Your Games Core Data Paul Goracke Core Data Potpurri, February 2014 http://bit.ly/1A5fWGr Marcus Zarra My Core Data Stack, March 2015 http://bit.ly/1KQaibt


  1. Integrating Core Data and CloudKit Jared Sorge

  2. Scorebook Remember Your Games

  3. Core Data Paul Goracke – “Core Data Potpurri”, February 2014 http://bit.ly/1A5fWGr Marcus Zarra – “My Core Data Stack”, March 2015 http://bit.ly/1KQaibt TaphouseKit – GitHub Project http://bit.ly/1e4AEwo

  4. CloudKit OS X Yosemite & iOS 8 Transport layer No black magic

  5. CloudKit Used by Apple iCloud Drive & iCloud Photo Library Used by third parties 1Password

  6. CloudKit Stack CKContainer

  7. CloudKit Stack Public CKDatabase Private CKDatabase CKContainer

  8. CloudKit Stack CKRecordZone Default Zone Custom Public CKDatabase Private CKDatabase CKContainer

  9. CloudKit Stack CKRecord CKRecordZone Default Zone Custom Public CKDatabase Private CKDatabase CKContainer

  10. CloudKit Stack CKSubscription (optional) CKRecord CKRecordZone Default Zone Custom Public CKDatabase Private CKDatabase CKContainer

  11. CloudKit Stack CKSubscription (optional) CKRecord CKRecordZone Default Zone Custom Public CKDatabase Private CKDatabase CKContainer

  12. CKRecord Store data using key/value pairs NSString, NSNumber, NSData, NSDate, NSArray, CLLocation, CKAsset, CKReference Use constant strings for keys recordType property is like a database table name

  13. CKRecord Initializers initWithRecordType: initWithRecordType:zoneID: initWithRecordType:recordID:

  14. CKRecordID 2 properties recordName, zoneID Initializers initWithRecordName: initWithRecordName:zoneID:

  15. CKRecordZoneID initWithZoneName:ownerName: Use CKOwnerDefaultName for ownerName Zone name is a string Use CKRecordZoneDefaultName for the default zone

  16. CKRecordZoneID CKContainer *container = [CKContainer sharedContainer]; CKContainer *container = [CKContainer sharedContainer]; CKDatabase *privateDB = [container privateCloudDatabase]; CKDatabase *privateDB = [container privateCloudDatabase]; CKRecordZoneID *newZone = [[CKRecordZoneID alloc] CKRecordZoneID *newZone = [[CKRecordZoneID alloc] initWithZoneName:@"ScorebookData" initWithZoneName:@"ScorebookData" ownerName:CKOwnerDefaultName]; ownerName:CKOwnerDefaultName]; [privateDB saveRecordZone:newZone completionHandler:^(CDRecordZone *zone, NSError *error) { //Error handling //Additional configuration }];

  17. CKRecord Creation CKRecordZoneID *zone = // CKRecordZoneID *zone = // CKRecordID *recordID = [[CKRecordID alloc] CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:self.ckRecordName initWithRecordName:self.ckRecordName zoneID:zone]; zoneID:zone]; CKRecord *gameRecord = [[CKRecord alloc] CKRecord *gameRecord = [[CKRecord alloc] initWithRecordType:[SBGame entityName] initWithRecordType:[SBGame entityName] recordID:recordID]; recordID:recordID]; [gameRecord setObject:self.title forKey SBGameTitleKEY]; gameRecord[SBGameScoringTypeKEY] = @(self.scoringType); gameRecord[SBGamePointsToWinKEY] = @(self.pointsToWin);

  18. CKAsset Blob storage Single initializer initWithFileURL: No support for NSData Attach to CKRecord instance as a value

  19. CKAsset NSURL *fileURL = // … url of path to file CKAsset *asset = [[CKAsset alloc] initWithFileURL:fileURL]; CKRecord *record = // record[@“asset”] = asset;

  20. CKReference Relate records with separate record types Relationships in a single zone only 1:many relationships many:many not officially supported Associate on the many side of the relationship Person Player

  21. CKReference Initializers -initWithRecordID:action: -initWithRecord:action: Set the delete action on the initializer CKReferenceActionDeleteSelf CKReferenceActionNone

  22. CKReference CKRecordID *personRecordID = // CKRecordID *personRecordID = // CKReference *personReference = [[CKReference alloc] CKReference *personReference = [[CKReference alloc] initWithRecordID:personRecordID initWithRecordID:personRecordID action:CKReferenceActionDeleteSelf]; action:CKReferenceActionDeleteSelf]; CKRecord *playerRecord = // playerRecord[SBPlayerPersonKEY] = personReference;

  23. CKSubscription Subscribes to changes of a record type or custom zone Can use a search predicate to determine matches Uses push notifications to alert you of changes Uses the remote notification system in iOS

  24. CKSubscription Save to the database for activation on a device Save once, then retrieve on other devices

  25. CKSubscription CKRecordZoneID *userRecordZone = // [privateDB fetchAllSubscriptionsWithCompletionHandler:^(NSArray *subs, NSError *error) { CKSubscription *subscription = [subs firstObject]; CKSubscription *subscription = [subs firstObject]; if (subscription == nil) { if (subscription == nil) { subscription =[[CKSubscription alloc] subscription =[[CKSubscription alloc] initWithZoneID:userRecordZone initWithZoneID:userRecordZone options:0]; options:0]; } } [privateDB saveSubscription:scorebookDataSubscription completionHandler:^(CKSubscription *sub, NSError *error) { //handle error }]; }];

  26. CloudKit Stack CKSubscription (optional) CKRecord CKRecordZone Default Zone Custom Public CKDatabase Private CKDatabase CKContainer

  27. Putting it together Sync is about upload, download, and conflict handling

  28. Make a Plan Database: public, private, or both? Using a custom record zone? Are you happy with your Core Data object graph? How to make specific things generic, and generic things specific?

  29. SBCloudKitCompatible @protocol SBCloudKitCompatible <NSObject> //Add to entities @property (nonatomic, strong) NSString *ckRecordName; @property (nonatomic, strong) NSDate *modificationDate; //Add to categories on the model objects - (CKRecord *)cloudKitRecordInRecordZone:(CKRecordZoneID *)zone; + (NSManagedObject *)managedObjectFromRecord:(CKRecord *)record context:(NSManagedObjectContext *)context; @end

  30. ckRecordName - (void)awakeFromInsert { [super awakeFromInsert]; NSString *uuid = [[NSUUID UUID] UUIDString]; NSString *recordName = [NSString stringWithFormat: @“SBGame|~|%@“, uuid]; /* SBGame|~|386c1919-5f25-4be2-975f-5b34506c51db */ self.ckRecordName = recordName; }

  31. modificationDate - (void)processCoreDataWillSaveNotification:(NSNotification *)notification { NSManagedObjectContext *context = // monitored context NSManagedObjectContext *context = // monitored context NSSet *inserted = [context insertedObjects]; NSSet *inserted = [context insertedObjects]; NSSet *updated = [context updatedObjects]; NSSet *updated = [context updatedObjects]; if (inserted.count == 0 && updated.count == 0) { if (inserted.count == 0 && updated.count == 0) { return; return; } } for (id<SBCloudKitCompatible> managedObject in inserted) { managedObject.modificationDate = [NSDate date]; } for (id<SBCloudKitCompatible> managedObject in updated) { managedObject.modificationDate = [NSDate date]; } }

  32. modificationDate - (void)processCoreDataWillSaveNotification:(NSNotification *)notification { NSManagedObjectContext *context = // monitored context NSSet *inserted = [context insertedObjects]; NSSet *updated = [context updatedObjects]; if (inserted.count == 0 && updated.count == 0) { return; } for (id<SBCloudKitCompatible> managedObject in inserted) { for (id<SBCloudKitCompatible> managedObject in inserted) { managedObject.modificationDate = [NSDate date]; managedObject.modificationDate = [NSDate date]; } } for (id<SBCloudKitCompatible> managedObject in updated) { managedObject.modificationDate = [NSDate date]; } }

  33. cloudKitRecordInRecordZone: - (CKRecord *)cloudKitRecordInRecordZone:(CKRecordZoneID *)zone { CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:self.ckRecordName CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:self.ckRecordName zoneID:zone]; zoneID:zone]; NSString *entityName = [SBPerson entityName]; NSString *entityName = [SBPerson entityName]; CKRecord *personRecord = [[CKRecord alloc] initWithRecordType:entityName CKRecord *personRecord = [[CKRecord alloc] initWithRecordType:entityName recordID:recordID]; recordID:recordID]; personRecord[SBPersonFirstNameKEY] = self.firstName; personRecord[SBPersonLastNameKEY] = self.lastName; personRecord[SBPersonEmailAddressKEY] = self.emailAddress; if (self.imageURL) { CKAsset *imageAsset = [[CKAsset alloc] initWithFileURL:[self urlForImage]]; personRecord[SBPersonAvatarKEY] = imageAsset; } return personRecord; }

  34. managedObjectFromRecord:context: + (instancetype)managedObjectFromRecord:(CKRecord *)ckRecord context:(NSManagedObjectContext *)context { CKRecordID *recordID = ckRecord.recordID; SBMatch *match = [SBMatch matchWithCloudKitRecordName:recordID.recordName SBMatch *match = [SBMatch matchWithCloudKitRecordName:recordID.recordName managedObjectContext:context]; managedObjectContext:context]; if (match.modificationDate != nil && ckRecord.modificationDate < match.modificationDate) { return match; } match.date = ckRecord[SBMatchDateKEY]; match.monthYear = ckRecord[SBMatchMonthYearKEY]; match.finished = [ckRecord[SBMatchFinishedKEY] boolValue]; match.note = [ckRecord objectForKey:SBMatchNoteKEY]; …

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend