Sync multiple devices with Core Data - core-data

I have a coredata app that I would love to be able to share the same data with multiple devices, possibly with iCloud/cloud kit. I am not sure where to start, or how to go about it? The only thing I can think of, but still not sure how to do, would be to sync the SQLite files with iCloud? Not sure if thats a good idea or not? I just recently converted my app over to swift 3 and iOS10 core data code. The only way I am able to share data between devices currently is thru iTunes files sharing.
For whatever reason this topic is hard to find modern info on.

Core Data doesn't have support for this. Except for the built-in iCloud sync, but that's deprecated as of iOS 10.
You could use CloudKit to sync data, but you'll have to write your own code to convert between Core Data's persistent store and CloudKit's online store. It's not impossible but it's certainly not automatic.
Syncing the SQLite file is not a good idea unless you really want to corrupt the data.

Related

Storing MP4 Files in Cassandra?

I am currently considering whether I should be storing media in an apache cassandra database. The use case is that the site will be taking uploads from users for insurance claims and will need to store the files so that they cannot be accessed outside the correct permissions and at the same time they need to be able to be streamed. If I store them on a file system, I have to deal with redundancy backups and so on using file system based old tech. I am not really interested in dealing with a CDN because many of them are expensive but also I the permissions to the whether you can view the content depends on information in the app such as which adjuster is assigned to the case and so on. In addition I want to stream the files rather than require download and view which would be the default mode with requests against a CDN. If I put them in cassandra it will handle the replication, storage and I can stream the binary data out of the database to the user with integrated permissions. What I am concerned about is if I will run into problems with cassandra rows having huge HD video files that are sometimes 1 to 2 hours long (testimony).
I am interested in the recommendations of Cassandra users concerning this issue. How would to solve the problem. Any lessons you have learned that I can benefit from. Would you suggest anything specific about the video tables if I go with cassandra storage? Is there any CDN that will stream, not require download, allow me to plug in permissions and at the same time be open source?
Thanks a bunch.
Cassandra is definitely not designed and should not be used as an object store. I've worked on plenty of use cases where Cassandra was used as the metadata store alongside the object store/CDN and can complement them quite nicely.
Check out KillrVideo for inspiration: https://killrvideo.github.io/
This seems like a good key-value usecase for Streaming LOB support in Oracle NoSQL Database. You might want to look at this - http://docs.oracle.com/cd/NOSQL/html/GettingStartedGuide/lobapi.html

How to sync records between Core Data and CloudKit efficiently

I'm currently learning how to use CloudKit Framework and lack of documentation or examples showing how to sync Core Data and CloudKit.
I have watched all WWDC videos (2014, 2015, 2016) Dedicated to CloudKit, but none of them telling us how to implement syncing with Core Data. I can't find any fresh examples, tutorial or books, showing how to implement this syncing.
I know that it is effective to use Operations API by CloudKit (not Convenience API) and to Subscribe to changes as it said in the new WWDC 2016 videos, dedicated to CloudKit, but mapping with CoreData is a real problem.
For example, let's say I would like to create an app similar to Notes app. while offline, user can create his notes and work with them saving them to his core data database. When the device going online the app checks what changed on the server and saves newly created records to server (CloudKit).
When the app starts, it also fetches for changes from the CloudKit and if there are changes , it updates local cache (Core Data) with the new changes.
I would appreciate to have a common pattern of syncing. Where to place syncing with Core Data methods and how they should look like?
Would appreciate any information or help about this.
I'm using Swift 3, Xcode 8 , iOS 10.
As of iOS 13, there are new API's that simplify this synchronization for developers. I would recommend you to watch the WWDC19 session about the new synchronization between CoreData and CloudKit. Please note that these new API's only work for iOS 13+.
Video: https://developer.apple.com/videos/play/wwdc2019/202/
In short, you need to start using NSPersistentCloudKitContainer instead of NSPersistentContainer. This will let the syncing work automatically using automatic conflict resolution with a last-writer-wins merge strategy. If you want to build a good working app, you'll also need to do some modifications to improve the syncing for your app.
Official documentation can be found at:
Setting Up Core Data with CloudKit
Syncing a Core Data Store with CloudKit
Data modeling for collaboration (conflict-free replicated data type)
At the end of the session they also demonstrated an example of better sync merging than the default 'last-writer-wins merge strategy'. The usage of Causal Trees allow multiple users to edit the same string (and to some extend other types of data) without losing any data. I would really recommend everyone to read this article from Archagon that describes how this works and how to implement it (also with CloudKit syncing, but not the new automatic one). As demonstrated in the session, you can also implement this with the new automatic syncing between CoreData and CloudKit.
Core Data already provides the user with the ability to sync to iCloud. There's no need to use CloudKit.
Design For Core Data In iCloud
But yes, Core Data with iCloud has been deprecated. Even so, it has not been discontinued, and there are no immediate plans at apple to discontinue it, they just want to discourage its use. But it also has problems with rationalising updates from multiple devices.
In any case, I have been looking into the question of how to do this with cloud kit myself. Two answers; the first is to use the following;
Seam in GitHub
The second is to do it manually;
Designing for CloudKit
The key here is that Cloud Kit needs the record metadata to be able to handle record updates reliably, so you have to save that metadata in your Core Data database. The CKRecord class includes a method encodeSystemFields(with:) which will encode those fields into a Data record that can be stored in your database, and then your can use the appropriate decoder when you need to restore the CKRecord.
Anyway, I am about to start doing this myself. I'll update this with more information when I have it.
Apple has recently published a guide that seems to answer this question. Check out Apple's Maintaining a Local Cache of CloudKit Records to see how to store CloudKit data on device.
While this guide doesn't provide sample code to write to the device, it does answer the rest of the question. This tells you how to fetch changes from CloudKit and create data which can be stored on the device.

Using existing database in Firefox OS app

I don't know much about FirefoxOS hence this question.
I have an android app that ships with already prepared data saved in SQLite database. In the runtime the app copies that db to the device storage and uses it for reading and writing data. This is much more efficient than creating empty DB file and inserting data when the app first starts(e.g from JSON).
I was wondering how can I achieve the same thing in Firefox OS? Is there any way I can create IndexedDB, fill it with data and then add it to the app package as an asset?
Unfortunately this behavior is not yet supported. As Fabrice Desré mentioned in bugzilla, some of the files to achieve this behaviour is specific to gaia apps, which gecko does not have access at the moment.
By now, you will have to stick with the less efficient method (depending on the size of your db, the difference isn't that big).
Hope I was able to help,
cheers

Checking iCloud for existing content

What is the best way to check iCloud for existing data?
I need to check that data doesn't exist on the local device, or iCloud so I can then download it.
Since you included the core-data tag I'm assuming you mean that you're using Core Data rather than iCloud file APIs or the ubiquitous key-value store.
With Core Data's built-in iCloud support, you check on existing data in exactly the same way as if you were not using iCloud. Once you create your Core Data stack, you check what data exists by doing normal Core Data fetches. There's no (exposed) concept of local vs. cloud data, there's just one data store that happens to know how to communicate with iCloud. You don't explicitly initiate downloads-- they happen automatically.
At app launch time when you call addPersistentStoreWithType:configuration:URL:options:error:, Core Data internally initiates the download of any data that's not available locally yet. As a result this method may block for a while. If it returns successfully, then all current downloads can be assumed to be complete.
If new changes appear while your app is running, Core Data will download and import them and, when it's finished, will post NSPersistentStoreDidImportUbiquitousContentChangesNotification to tell you what just happened.
This all describes how Core Data's iCloud is supposed to work. In practice you'll probably find that it doesn't always work as intended.
Thanks to #Tom Harrington for pointing out, this error is nothing to do with the developer/coding - it's purely to do with iCloud/Apple/connection issues.
More on this SO answer I found.

Can HTML5 localStorage in Cordova/Phonegap app be synced to iCloud?

I have a Phonegap/Cordova app that runs on iOS. It saves it's data into HTML5 localStorage.
I'm trying to work out if it's possible to sync the localStorage data (using iCloud) to other iOS devices, and even OS X.
From what I can see, in iOS localStorage is actually implemented as a SQLite database, which (when using Phonegap/Cordova) is written to the app's Documents directory:
Documents/Backups/localstorage.appdata.db
I also understand that there are three main ways of storing data in iCloud:
Key/Value storage
UIDocument / NSDocument
Core Data
I know I can't use the Key/Value iCloud storage method, because I have more than 1MB of data to store, and the limitation is 1MB per app with that method.
This question, I believe is talking about the UIDocument method, and asks if it is possible to store a SQLite db file in iCloud using that method. The answer is no because the database may become corrupted.
So that really leaves the Core Data method.
So my question is - would this work? Could I sync the localStorage.db file to iCloud using Core Data?
I've never used Core Data and don't know much about it. I'm just wondering if it would be possible, or if there is something else I don't understand.
Are there any other ways to sync localStorage data between iOS devices or OS X ?
The answer unfortunatly appears to be no, Core Data cannot be used with HTML5 localStorage
Core Data can not be used with SQLite databases other than ones created with Core Data. If you try to, you get this error in XCode:
SQLite error code:1, 'no such table: Z_METADATA'
This is explained the Core Data docs:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFAQ.html#//apple_ref/doc/uid/TP40001802-SW2
Although Core Data supports SQLite as one of its persistent store
types, the database format is private. You cannot create a SQLite
database using native SQLite API and use it directly with Core Data
(nor should you manipulate an existing Core Data SQLite store using
native SQLite API)
I still want to solve this issue though. I'm thinking of creating a Javascript API that mirrors the localStorage API. This would be a phonegap plugin that can call objective-c code, and effectively write it's changes to a Core Data database. The Core Data database should then be able to be synced to iCloud.
If it works, I'll come back and update this answer.

Resources