How to model Core Data after CloudKit in iOS app - ios

I'm working on setting up Core Data as a local cache of my CloudKit records. I want to model my Core Data models as closely to my CloudKit record types as possible to make converting between the two as easy as possible. As per CloudKit's recommendation, my records are designed with back-references to parent records instead of lists of references for performance reasons but also because I need to support more than CloudKit's 750 references limit. Should I keep this design for my Core Data models or is this not best practice? Thank you.

Related

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:
allow users to enter their data once and have it appear on all their devices.
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?
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
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.

Usage of Core Data other than a Database

i am new to this Core data. When i search for tutorials, I'm seeing this sentence Core Data is not a database everywhere on the internet.
If it is not a database, why are we using it as a database?
For what purpose Core Data is initially created?
Is there any other way Core Data was used before/will be used in
future (Other than as a DB)?
Sorry for my English.
Thanks for the time.. (:
Actually Core Data is a bridge between the code and the underlying database (like SQLite or XML...). Core Data is not a database, but uses SQLite (or XML...) for persistence. The main purpose of Core Data is to manage memory objects and object graphs easily without having to do it manually through a SQLite library for instance. It is possible to use Core Data without persistence is you want (using In-Memory stores).
Here is the documentation : https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/index.html#//apple_ref/doc/uid/TP40001075-CH2-SW1
Bye!
If it is not a database, why are we using it as a database?
"We" are not necessarily doing so, depending on who you mean by "we". Core Data can be used in a database-like manner, keeping in mind the Core Data vs. SQL differences others have noted. But that's not the only possible use.
Statements that Core Data isn't a database are mostly intended to prevent people from thinking of Core Data in the same sense as SQL. That sort of thinking leads to badly designed data models, since the approach is different. It can be used as a database in the generic sense of the storing structured data but it's important to not assume that it works like other databases you may have used.
For what purpose Core Data is initially created?
Is there any other way Core Data was used before/will be used in future (Other than as a DB)?
Core Data was created to fill what might have been perceived as a missing piece in Apple's frameworks. They generally take the MVC approach. There were classes to help in designing and implementing views (in these pre-iOS days that meant AppKit) and with controller classes (for example NSArrayController, also an OS X class). But model support was limited to NSCoding, which required a lot of repetitive code. Custom solutions also had trouble scaling to large amounts of data-- for example NSCoding doesn't help you load only part of a large document graph, because it recursively works its way through the entire object hierarchy.
Core Data was added with the purpose of making it easier to design and implement the model layer of an app. It's no accident that the document you edit to design the data is called a data model and not a schema.
The idea was (and is) that you could
Design your data model visually in Xcode
Create and use instances of your model objects
Read and save those objects in a file
...all without ever needing to write your own code to figure out how to convert your model objects to and from something that could be written into a file, or with the mechanics of opening a file, reading/writing it, and saving it. You'd just create objects as needed and then call save on NSManagedObjectContext. The small bit of code that was concerned with locating and opening the file was all pretty much the same in any app, so while it was still required it was mostly no longer the app developer's concern (and in iOS 10, NSPersistentContainer eliminates even this). You'd also get the benefit of only needing to load the parts of your object graph that you currently needed instead of loading everything every time.
As you've noticed, in practice Core Data is commonly used more or less like a database, and it works for that. But it's not designed to be limited to such uses.
Yes it is true , Core data is not a Database, though internally it saves data using sqlite. We use Coredata for persistent data which means we should be able to save the data and use it even after closing and reopening the app. There are various ways to store data like Sqlite,Plist,UserDefaults and CoreData. Coredata does not maintain any relations like SQlite. It means there are no keys like primary and foreign etc. Coredata allows you to deal with data in Object Oriented Approach. You can easily work with data operations even you don't have knowledge about DB queries.

What are the pros and cons of using multiple NSPersistentStores for a single model?

Let's say I have a single model but I want to save objects to more than 1 NSPersistentStores. Assuming I use a single NSPersistentStoreCoordinator to manage those stores, what are the pros and cons of this setup?
With regard to the original question (multiple stores, one coordinator):
The potential advantage of two stores under one PSC is that you can spread out the data between two sqlite files (assuming that's the store type you're using). This can be helpful for example if you want to ship a pre-populated sqlite file with your app (which you can easily update in subsequent releases by shipping a new file), while still having user-created data next to it.
The disadvantage is that handling relationships across different stores is more cumbersome than within one store.
With regard to another answer to this question (multiple coordinators):
There certainly are potential benefits of using multiple coordinators with the same store, primarily performance related. Any request to the coordinator will lock it, so that everybody else has to wait to fetch data or save data. By using two coordinators you can push the lock down to the sqlite file, where it comes and goes much quicker.
Furthermore, a sqlite store that uses write-ahead-logging instead of a rollback journal enables multiple reader, single writer access to the store. By using two coordinators you can take advantage of sqlite's concurrency abilities. Apple is using this pattern internally too.
See also Apple's WWDC 2013 session on Core Data and iCloud (can't link because of ongoing dev-center outage...)
But keep in mind that all this is pretty esoteric and not necessary in almost all cases.

Data model persistence considerations in iOS

I've been working with sqlite database in my iOS app for data persistence, and I'm now trying to decide if it is worth to learn Core Data. I've been reading some documentation and posts regarding its pros and cons, but I find that deciding when to use Core Data or Sqlite is not so clear (for example, Core Data VS Sqlite or FMDB…?).
I need some guidance to know if I should learn and use Core Data, or using Sqlite is enough for me:
Already having sqlite scripts, is it possible to build a Core Data model from data in sqlite database? Afaik, (correct me if I'm wrong) you can use sqlite to persist Core Data objects, but is it possible to operate in reverse?
Is it appropiate Core Data for handling several users data? I need to take into account that different users could log in into the app in the same device.
Thanks in advance
Core Data is a wonderful framework but while it generally uses SQLite behind the scenes, you shouldn't think of Core Data as a database engine, but rather more of an object persistence framework. If you've got a lot of SQL code (especially bulk updates and the like), it might not be worth converting to Core Data. But Core Data has lots of wonderful performance optimizations, iCloud integration, etc., so it's worth examining in greater detail.
If you want background on Core Data, I'd suggest the Apple video Working with Core Data.
If you just want to simplify your SQLite code, check out FMDB.
In answer to your questions:
Already having sqlite scripts, is it possible to build a Core Data model from data in sqlite database? Afaik, (correct me if I'm wrong) you can use sqlite to persist Core Data objects, but is it possible to operate in reverse?
You generally have to redefine your Core Data model. It cannot just open your existing SQLite database (though once you define your model, you could write code to transfer the data from SQLite to Core Data).
Is it appropiate Core Data for handling several users data? I need to take into account that different users could log in into the app in the same device.
Yes, you could. You'd have to define your model to handle this manually, though (e.g. add a user identifier field and manually code predicates/filters results accordingly, much like you'd have to do in SQLite).
AppsDev,
Only you can judge whether to use Core Data or to stick with SQLite. As you've referenced my answer above, you know my view -- use Core Data. Let me put it in your context.
The big win is the family of abstractions that come with Core Data and how they map onto the Objective-C object model. This is something you have to handle manually from a SQLite application. (Can you do it? Yes. You will, though, most likely make a custom interface that is tuned to your SQL schema. It will have little reusability. This is a long term problem.)
As to the question of predicates versus SQL queries, this is a difference in world view. That said, as predicates can be applied to both NSSets and NSArrays, they have a utility beyond that required by Core Data. Knowing how to use predicates will be of value. For example, you could easily perform a query to get a collection of records and then use predicates to filter them, say for the search of a table view.
Everyone needs to pick when they are ready to embrace a specific pattern. SQL experts, unsurprisingly, like to stick with what they know. Dynamic language aficionados will choose differently. For iOS/OS X, embracing the dynamic language path will have ever increasing value to you as a developer.
Hence, my recommendation remains: use Core Data.
Andrew

Core Data Design: better 1 model with 2 stores or 2 models and 2 stores?

I'm facing a design problem using core data in an iOS app.
I've got two stores, one will contain a sort of catalog, the other only user data.
I've read all those questions:
CoreData with multiple stores: configuration woes
Why might I want 2 or more Core Data models?
Can multiple (two) persistent stores be used with one object model, while maintaining relations from one to the other?
But what I still didn't get is if it is better two use one model on two persistent stores or two models merge them at runtime with two stores. What will be easier, eventually, to migrate?
The definite way to go here is have one data model with two stores, administered via two so-called configurations.
In the model editor you can define which entities belong to which configuration.
In code you specify the identifier string of each configuration when adding the persistent store.
See the WWDC 2012 video on Core Data and iCloud that explains it really well.

Resources