groue / GRDB.swift

A toolkit for SQLite databases, with a focus on application development
MIT License
6.73k stars 696 forks source link

CloudKit integration #385

Closed corysullivan closed 6 years ago

corysullivan commented 6 years ago

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

groue commented 6 years ago

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?

sobri909 commented 6 years ago

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.

corysullivan commented 6 years ago

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

zrfrank commented 4 years ago

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.

osteslag commented 4 years ago

I’ve done my own CloudKit integration where iCloud is the truth and GRDB serves as a local cache, sync’ing with the cloud. Although I do have some experience with CloudKit, I haven’t taken the time and effort to think about how GRDB could generally support or integrate with CloudKit. I simply can’t 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’t complain, of course :-)

groue commented 4 years ago

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

zrfrank commented 4 years ago

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

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,


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?

mentrena commented 4 years ago

@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

ahartman commented 4 months ago

Dear Gwendal,

GRDB is now well settled in my Patients app. I was reading on syncing via CloudKit of my SQLite database. The idea is to leave the refreshing of data to running my app on my Mac and treat my iPad and iPhone as read-only devices.

I found an interesting Github entry that does SQLite syncing over Cloudkit on top of GRDB! Take a look at gerdemb/SQLiteChangeSetSync on Github.

Regard, André Hartman

groue commented 4 months ago

Hello @ahartman,

I'm happy with leaving the CloudKit sync facet to the community. The current GRDB apis should not prevent anyone from building their CloudKit sync solution. And I don't myself have any interest in CloudKit, whereas a robust implementation requires a lot of dedication and tests.

Have a look at https://github.com/aaronpearce/Harmony: it provides CloudKit sync for GRDB.

FledgeXu commented 3 weeks ago

Hi everyone, sorry to bother you. I would like to leave some comments for future viewers who want to support CloudKit for GRDB.

If you only need to support iOS 17 or newer, you can use the CKSyncEngine, Jordan Morgan has a great article talking about how to use it. The key part is translating GRDB record to theCKRecord, for this part you can check Harmony's code.