Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sync an iOS app that uses core data to cloud

I have written an app with Swift 2 using Core Data for persistence.  I am thinking about adding a feature to also persist in the cloud.  I have read tutorials on Realm and CloudKit, but haven't seen great examples on using them on top of (or along with) Core Data.

I want to:

  1. allow users to enter their data once and have it appear on all their devices.
  2. let users sync some of their data with a user of their choice.

Can I keep all my Core Data logic and simply add some server calls during CRUD operations using CloudKit (or some other framework)? For example, I use NSFetchedResultsController for several of my tables, does it make sense to continue to use it while using CloudKit?

like image 925
Coder1224 Avatar asked Oct 14 '16 04:10

Coder1224


Video Answer


2 Answers

CloudKit and CoreData do not automatically work together seamlessly, so you will need to write that logic yourself.

There are different types of iCloud storage options, one or two of which do seamlessly integrate with CoreData, but CloudKit is not one of them, and CloudKit is what you will need to use if you have aspirations of enabling your users to share data with others.

AKA: You will need to do the heavy lifting yourself, but if you use good design practices you can do the work once without having to rewrite much of your existing code.

So, here's something similar to what I did in one of my projects that used both frameworks:

  • Create Core Data object model and NSManagedObject subclasses like you almost certainly already have.

  • Turn on CloudKit in Xcode project capabilities and log in to CloudKit Dashboard

  • Use CloudKit Dashboard to design your record model modeled after your Core Data entity model

  • (Back in Xcode) Create methods somewhere (most conveniently as extensions to your NSManagedObject subclasses) that know how to create the given Core Data object from a CKRecord, and to create a CKRecord from a Core Data object.

  • Create one or more Swift classes dedicated to dealing with your CloudKit records and synching them with Core Data. This class(es) would be responsible for performing all CloudKit operations at a high level, including fetching, adding, deleting, modifying, etc. You can design this public API however you want (it should be customized to your needs), but this class would most likely use the methods you created in the previous step to convert to and from Core Data types.

With this approach, your CloudKit specializing class (we'll call it CloudBrain) does all of the heavy lifting, and if you want you can make it do it all behind the scenes. For example, you could define another class, SyncBrain, that would automatically listen for changes in the Core Data managed object context, and call corresponding methods on CloudBrain to ensure all changes are being kept in sync with iCloud. It would also need to do the reverse, listening for changes in iCloud and applying them to Core Data. This will of course require fetching changes initially from CloudBrain and you'll also want to look into CKSubscription for real-time updates.

The beauty of this approach is that if you set up all of that correctly, you can keep all of your other code the same, because every time your other classes interact with Core Data, SyncBrain automatically ensures that all changes in Core Data are reflected in iCloud and vice versa.

As for sharing with other users, this feature is new in iOS 10 and it does not appear as though Apple has yet updated the CloudKit Quick Start. You should therefore watch What's New with CloudKit from WWDC this year.

Important Note: When designing your record model in CloudKit Dashboard, be sure to follow the iCloud Design Guide and not have parent record types with fields holding arrays of a child record type. This is not great performance. Instead, define the child record type to have a single CKReference field that points to its parent. That way if you need the children for a parent, you can just create a query that requests all objects with their parent set to the parent you want (as opposed to having to wait for all of the children to download when all you wanted was the parent).

Here are some WWDC sessions. Older sessions still contain very useful information but some of it is out of date.

  • 2014 – Introducing CloudKit (A must-watch to get the concepts correct)
  • 2014 – Advanced CloudKit
  • 2015 – What's New in CloudKit
  • 2015 – CloudKit Tips and Tricks
  • 2016 – What's New with CloudKit
  • 2016 – CloudKit Best Practices
like image 123
Matthew Seaman Avatar answered Nov 15 '22 06:11

Matthew Seaman


In Xcode 11, you can now mirror Core Data to the cloud. It seems really easy to do as well. You just need to use NSPersistentCloudKitContainer instead of NSPersistentContainer. Your data will sync with CloudKit automatically.

See the documentation for more information.

PS. As of writing this, this is in beta.

like image 20
Chris Slade Avatar answered Nov 15 '22 04:11

Chris Slade