Local Cache of CloudKit Records - ios

There's a chapter called Maintaining Local Cache of CloudKit Records in CloudKit documentation on Apple's web site. However, everywhere online people say it's close to impossible to store offline data with CloudKit. I'm relatively new iOS developer. Did anybody tried implementing offline data storage (on device) as per Apple's docs?

If you want true, offline-first data for your app, then yes, you need to add a database of some kind.
Every time you update a record, save it to your database and push the updated record to CloudKit. You can also subscribe to CloudKit changes and update your local database as record changes come in.
Core Data and SQLite are common options. I happen to use the Realm database, which I consider to be a bit simpler to use than Core Data or SQLite. I set it up so that my app's UI only interacts with the offline data in the database (so that it's always available). CloudKit and my Realm database work together to keep the data up-to-date, but my UI never tries to rely on the presence of transitory CloudKit records.
I hope that helps.

Related

Core Data Values Accessed by Multiple Users when logged in (iOS Swift)

I have an app where a UITableView is used to represent a friends list. Now, this table is updated by values stored in core data, and I'm downloading friend values to core data via Parse. Instead of accessing Parse to update the tableView directly, I decided to update Core Data and then the tableView because I need the friend information in other parts of the app, and thought it would be more efficient to use Core Data than to have calls to Parse again and again. Everything works fine!
However, my app has a log in system before users can use the app. And when I created another dummy user to test it, I found that the friend values stored in Core Data by my actual account were being used to update the friend list tableView! When actually the tableView should be empty (new user).
I don't know exactly how Core Data works but I figure it uses some segment of the device's memory to store entities. My question is this, is it possible to use Core Data to store private information related to a particular user that can't be accessed by other users that log into the same device? Or should I continue to make calls to Parse whenever I need information?
Hope you guys understood my question, thanks!
iOS is not a multi-user system. Your app stores its files in a sandboxed folder structure and this sandbox is independent of any user logins you have implemented in your app.
When a new user logs in (or, if you prefer, when a user logs out) it is up to you to remove any data you have stored in Core Data that you don't want another user to have access to.
Parse can save data offline by Local Storage or cache the request by Cache Policy
They are much faster than creating your own database (by CoreData).

Core Data coexistence with network service for the "What if the user cannot connect?" situation

I am looking for the proper way for a swift iOS app that relies on, in my case: AWS but has a local persistent data store so that every possible feature of the app can be used offline.
So far, I went from a pillar or two of Core Data to a full core data stack and it is becoming difficult to foresee how to coexist with AWS DynamoDB. While DynamoDB is of a NoSQL structure, Core Data in the way I have set it up is that of a SQLite persistent data store.
I need to eventually download tables and primarily use AWS for most situations where users are online, but if they want to work offline, I need to be prepared. Perhaps I should try to create a singular User entity, because why would I want to store other users offline? Then once internet is active, I could try to push it to my DynamoDB Users (plural) table.
I have created Entity's in Core Data such as Users, Authors, Profile.
In the scenario a user opens the app and has no internet access, I am planning on inserting a Users entity and my goal is to correctly populate Authors and Profile, because this offline end user is definitely a User, and I want to setup at least a Profile for them as well so that they can later tweak with customizations.
I have maybe too many relationships. I want to do this correct.
In simple situations, I understand a Person Entity might have a father, mother, child and how they can all fit nicely into Person, but since I have entities with enough unique attributes that I thought I need to create their own entities,
How should I go about creating an entity that certainly makes a User/Users record and establishes a Profile?
Short answer is this:
Core Data is your local cache whether you are offline or online. If you are online then the app should refresh the Core Data cache when appropriate.
When offline the app should not update the cache.
The User Interface in either case is identical. The user interface feeds from the Core Data cache ONLY.
I suggest watching my talk on MVC-N that is hosted by realm.io.

Can Realm be used as a persistence model to represent a CloudKit public database?

I'd like to use Realm as a persistence model to represent my CloudKit public database. Is this possible?
Specifically, I would like to use CloudKit to take a Realm data model and store it in my CloudKit public database.
This would overcome my current issue of having to fetch data from CloudKit every time the app is loaded in to memory. Without a local data model, when there is no internet connection, no data is fetched because there is no persistence.
If the app is removed from memory, any data held in the app that was fetched from CloudKit is also removed from memory.
It is possible, you just will have to write the code to convert your model objects to/from CKRecords that can be sent to CloudKit.
If you were trying to use the private database, I would suggest using this library, which is compatible with both Realm and Core Data (disclaimer, I'm the author): https://github.com/mentrena/SyncKit
Another solution, for Core Data, is https://github.com/nofelmahmood/Seam
However, the public database doesn't allow to query for changes, so you would have to roll out your own implementation to keep a cache of some record query, rather than a fully synchronized local cache of your whole model.
In my opinion, if you want to use CloudKit, you should use Core Data as the persistent store. It works very well together.
If you prefer modern solutions, try Realm Mobile Platform https://realm.io/products/realm-mobile-platform/
Also, you can try to write some custom backend with Vapor and use Realm as the persistent store.

One way sync with Core Data

I am about to build an internal-only iOS app for storing simple business data. The data store will consist of a single entity only, with one entry per day. To start with there will be around two years worth of data (~750 entries).
I want to set the app up to do one-way syncing only. i.e. Only one person can enter data, but others can read it. iCloud is out as it only works for a single user account.
Is there a lightweight way to sync this datastore out from the single write user to the other read users? Setting up a full sync system seems overkill for this case.
Instead of iCloud, you could use one of the online backends such as Parse.com or Simperium. They would allow you to share data using a db and also provide for user accounts, authentication etc. If you want to run the server locally you can investigate DataKit.

How to split an iOS sqlite db?

I have an existing iOS app that uses core data for app data and user data. My problem is that updating app data is a nightmare (my first app, so I didn't do it ideally the first time). I would like to split the app data and user data into 2 separate sqlite dbs (or stores, correct me if my terminology is wrong).
Any tips would be appreciated.
Having two sqlite files is a good idea. The pain is splitting them now.
Create a new store that only exists in your app bundle. Make sure the data is unchanged from when you first released the app.
You are going to need to walk the "user" store and find all of the data that is identical to what exists in the "reference" store and delete it. If the user has changed that data then I would leave it and let the user sort out duplicates.
Once that is complete your app can resume normal function and load up both stores. I would set a flag somewhere so that you know this has been done and you don't run the check on every launch. The "user" store's metadata is a good place.
Note, this will need to be done before the user can "use" your app. This probably means changing your launch routines so that if a migration and filter is needed you tell the user what is going on.
I don't think having multiple persistent stores is the right solution. You can simply have separate entities within a single persistent store. Core Data will handle it properly.

Resources