Grdb.swift: CloudKit integration

Created on 15 Jul 2018  路  8Comments  路  Source: groue/GRDB.swift

Any plans to integrate with CloudKit? or any references/guides on how to achieve this?

question

Most helpful comment

@groue I'm not familiar with GRDB myself, but I can say the approach suggested by @zrfrank is precisely what I use in SyncKit.
I have a synchronisation layer that deals with CloudKit and fetches changes incrementally using CKFetchRecordZoneChangesOperation and other CloudKit operations.
And then there's a model adapter layer that deals with translating CKRecords to model objects and also tracking changes to the local model and providing the former layer with CKRecords to upload those changes to CloudKit.

Currently I provide model adapters for Core Data and Realm, but I suppose it should be possible to create a new one for GRDB (Would need a new class conforming to https://github.com/mentrena/SyncKit/blob/master/SyncKit/Classes/QSSynchronizer/ModelAdapter.swift). If that's something you'd like to look into I'd be happy to help (not sure I'd have time to do it myself short-term)

Another solution you might find worth looking at, although I haven't personally used it, is https://github.com/caiyue1993/IceCream

All 8 comments

Hello @Sully73,

You're the second one to ask this question. First was @oleganza: https://twitter.com/oleganza/status/1004817666891059206

I totally lack CloudKit experience: it's difficult for me to provide a proper answer.

Maybe you can help: What do you lack today? What do you think would be desirable/possible?

I've got CloudKit integration for LocoKit's GRDB layer. But that code isn't open source (yet?).

The very short version is you want to use CloudKit subscriptions for observing changes from the CloudKit side, and on the GRDB side you want to have some extra fields on your tables, for knowing when the rows need to be saved/updated to CloudKit.

protocol CKObject: PersistentObject {
    var ckRecord: CKRecord? { get set }
    var ckRecordName: String? { get set }
    var ckLastSaved: Date? { get set }
}

That's part of the protocol I use, which my database models implement. The ckRecordName and ckLastSaved allow you to know whether the object needs updating on CloudKit or not. Uh, you also need to keep a lastSaved field for knowing when the row was last updated on the GRDB side.

Yeah, there's a fair bit involved in it. This is only scratching the surface really, and I don't have the time to write up a proper howto just now, unfortunately.

I recommend hunting around for a generalised tutorial on the process, as it should be the same as for any other database layer. The patterns are fairly universal.

Thanks, @sobri909 and @groue. I don't have any direct experience with CloudKit myself, other than the basics. However, I did come across this article, which certainly helps. Also, Yap database supports Cloudkit, so I intend to study that code as well... Time to sink my teeth into CloudKit

I also second the support for CloudKit. For the moment, the only thing preventing me from using GRDB(and leave Core Data behind) is the lack of cloud sync.

I鈥檝e done my own CloudKit integration where iCloud is the truth and GRDB serves as a local cache, sync鈥檌ng with the cloud. Although I do have some experience with CloudKit, I haven鈥檛 taken the time and effort to think about how GRDB could generally support or integrate with CloudKit. I simply can鈥檛 envision a good general-purpose API for it on the spot.

The fact that GRDB is so focused on local persistence is also one of its strengths. If I could just tick a checkbox to get a magical CloudKit integration, I wouldn鈥檛 complain, of course :-)

Hello @zrfrank and @osteslag. The plain truth is that I haven't used CloudKit yet, so my own ideas are pretty fuzzy: https://twitter.com/groue/status/1263135372743184391

My main message to anybody listening is that a much welcomed contribution would be to define what "CloudKit support" could mean for an SQLite wrapper like GRDB. What are the desired use cases? Is it only a matter of implementing a new set of APIs, or would it require modifications in the existing GRDB layers (SQL, records, query builder)?

Finally, I suggest having a look at https://github.com/mentrena/SyncKit "Automatic CloudKit synchronization". I don't quite know what it does exactly, but this library which is well supported can drive both Core Data and Realm through plugins. Maybe it is possible to develop a GRDB plugin for SyncKit?

cc @mentrena

I think the use case mentioned by @osteslag, "iCloud is the truth and GRDB serves as a local cache, sync鈥檌ng with the cloud", would be a very typical one. In such case,

  • GRDB not only persists the database to the on-device local SQLite DB file,
  • GRDB also persists the entire database (or selected tables) to the cloud, and
  • GRDB manages the synchronization between the local and cloud.

For example, a "magical integration" could be, an update on an iPhone, could trigger the update on iPad and macOS, i.e. the database is completely in-sync across devices.

Naively, I would guess such integration would require a synchronization layer managing,

  • the mapping between SQLite and the CloudKit;
  • the synchronization between local and cloud.

A further and probably non-realistic idea is that, as GRDB is entirely backed by SQLite and any app that's using GRDB is designed with SQLite in-mind, GRDB can just synchronize a pip-line of the SQL transactions?

@groue I'm not familiar with GRDB myself, but I can say the approach suggested by @zrfrank is precisely what I use in SyncKit.
I have a synchronisation layer that deals with CloudKit and fetches changes incrementally using CKFetchRecordZoneChangesOperation and other CloudKit operations.
And then there's a model adapter layer that deals with translating CKRecords to model objects and also tracking changes to the local model and providing the former layer with CKRecords to upload those changes to CloudKit.

Currently I provide model adapters for Core Data and Realm, but I suppose it should be possible to create a new one for GRDB (Would need a new class conforming to https://github.com/mentrena/SyncKit/blob/master/SyncKit/Classes/QSSynchronizer/ModelAdapter.swift). If that's something you'd like to look into I'd be happy to help (not sure I'd have time to do it myself short-term)

Another solution you might find worth looking at, although I haven't personally used it, is https://github.com/caiyue1993/IceCream

Was this page helpful?
0 / 5 - 0 ratings