IceCream icon indicating copy to clipboard operation
IceCream copied to clipboard

Add sharing support

Open insidegui opened this issue 7 years ago • 21 comments

CloudKit now has the sharing feature. It would be cool if we could have a way to sync records using the shared database as well (and maybe an easy way to create shares using IceCream)

insidegui avatar Nov 29 '17 01:11 insidegui

Yes, you're right. Supporting shared database is appended to the to-do list.

We can do that in the future enhancement of IceCream.

caiyue1993 avatar Nov 29 '17 07:11 caiyue1993

Hello,

Is there any news on when Shared databases might be supported?

How about Public? Public databases would be my real interest.

Thanks and keep up the good work. IB

ianbradbury-bizzibody avatar Mar 02 '18 10:03 ianbradbury-bizzibody

Hi @ianbradbury-bizzibody ,

Thank you for your attention on IceCream. Shared database will be supported in the near future, but there is no a exact time. So just be patient :)

Or you could make a pr to us. That would be great.

(And I don't know why you have the needs for public database?)

caiyue1993 avatar Mar 02 '18 11:03 caiyue1993

I also have the need for public database support in order to share data to all users in my app.

I don't mind adding this with a little guidance.

matadan avatar Mar 06 '18 09:03 matadan

Like @matadan - I have a need to share/replicate a "source" data set across many devices. Of course the data set also has multiple record types.

ianbradbury-bizzibody avatar Mar 08 '18 07:03 ianbradbury-bizzibody

too much modify so I made another repo, which is not out of box currently

purkylin avatar Jun 06 '18 09:06 purkylin

I'm also interested in the sharing feature in cloudKit using IceCream if possible. I'm definitely interested in creating a PR. Jotting down my current state for anyone that wants to help out with this.

I'm seeing that a new CKRecord record is created whenever we call someRealmObject.record. This seems to be my starting point as I'd assume I should determine if the share actually exists within iCloud. The issue here is that the change hash is incorrect when we dynamically create the CKRecord. My current workaround is to replace the call for myRealmObject.record with a CKFetchRecordsOperation with myRealmObject.recordID, the success results of that is a CKRecord object, with which I can create the CKShare.

So far so good on the owner end.

Now on the participant end I need to retrieve the shared object from the shared database. As IceCream only supports the private database, this is likely where the list of the issue occurs. I'm going to start stabbing around with this over the next few days. If anyone's got any pointers let me know.

rodericj avatar Jul 10 '18 20:07 rodericj

Hi, @caiyue1993 Thank you for this awesome repo. I was wondering if there is any news on shared database support?

omerbaskurt avatar Jan 04 '19 19:01 omerbaskurt

Our implementation leaves a bit to be desired unfortunately. My take on this is that an abstraction through IceCream may not be the best approach. Your realm object really has no way to interact with the CKShare objects. I'm open to literally any suggestion to make it work through this project.

rodericj avatar Jan 04 '19 20:01 rodericj

After looking at this a bit more I'm stuck on one of the fundamental benefits of IceCream being a bit of a blocker for this.

Fetching information from CloudKit

i think I have my local implementation so when you get a change FROM cloudkit, it should handle the exchange appropriately. For instance, if something comes in on the shared database, the realm will pick it up but then the other databases (private and public) won’t pick up the changes from realm.

Adding to CloudKit from user action or something on the client side:

Adding an object to realm, the interface from the view of the developer looks like this:

try! realm.write {
    realm.add(cat)
}

At which point, the notificationToken for Public Private and Shared all pick up this addition and attempt to send 3 different objects up to cloudkit which is problematic. I believe I'd need to expose something like this in the IceCream API (which currently there isn't much of an interface)

someIcecreamObject.add(cat, .public)
// or
someIcecreamObject.add(cat, .private)

Which internally does something like this:

try! self.realm.commitWrite(withoutNotifying: [publicNotificationToken,
                                               sharedNotificationToken])

This fundamentally changes the spirit of IceCream and I could use a bit of help trying to figure out how to proceed.

I've pushed a commit here which has all of the changes I'd made. I'm happy to talk about this with @caiyue1993 or anyone interested in doing a Zoom meeting on this. Or async in this thread.

rodericj avatar May 07 '19 00:05 rodericj

hey @rodericj @caiyue1993 - I'm new to IceCream, literally just found it today and tested out the example, it seems like a brilliant solution all round.

As for sharing, for the right kind of app it's so useful (and often necessary). The beauty of using CloudKit is it just works for the user straight out the box, no signing up or anything like that needed. I reckon whoever nails a simple, out the box solution for developers to use, will be a hero!

I recently released Magpie (check it out www.getmagpie.app) - its kinda a photo based list app - which uses CloudKit Sharing to let users share individual lists. A friend of mine worked on all the sync side of things (I'm more the design / 'front end' side of things). It was really difficult to do, like crazy difficult, mainly because it's so badly documented by Apple, and there's loads of weird things to catch you out. It's really 'simple' as a demo, but in a real world app it's hugely time consuming and hard to get right. I personally don't want to go near it again...not at least without the help of something like IceCream.

I'm hoping maybe some anecdotal info from how we did it might help get it solved in a much more 'out the box' way using IceCream and Realm? (I'm going to confess right now, it's a bit too deep for my coding ability, but I can help with the concept of what we did)

So, we used CoreData / CloudKit and Ensembles as the sync engine (www.ensembles.io). We created the idea of a 'MultiStoreManager', each 'list' has it's own core data store, which is managed by it's own 'ensemble'. There's then a 'master' ensemble that manages all it's child ensembles. This way, the whole app syncs for user A, but he can share Listxxx with user B.

I've played around with Realm in the past, essentially to try to do this sharing thing directly in Realm...not too deeply, but enough to understand any user can have multiple realms. My thinking was always - each 'list' is it's own realm, User A grants permission to User B to access Realmxxx

Maybe this is the key here with IceCream too, using multiple realms? So, someIceCreamObjectA and someIceCreamObjectB actually have their own realms behind the scenes, that are converted over to CLoudKit in a way that also keeps them separate, and able to be individually shared.

Perhaps I'm going completely off topic here with how IceCream fundamentally works (like I say, my thing is design an UX, I'm pretty decent with Swift but when it comes to gnarly data stuff like sync, I'm a bit out of my pay grade)..but maybe the concept of this idea might help?

Just trying to input to this cool project in some small way 😁

Emile

emilebennett avatar Jul 04 '19 15:07 emilebennett

Any update on shared databases? Is this something that is going to happen soon?

kishinmanglani avatar Sep 27 '19 03:09 kishinmanglani

Afaik there are no concrete plans to implement this. Adding CKShares is fundamentally different than what exists now. My recommendation would be to roll your own if you need this for your implementation.

I gave it a shot in May, and got about 60% of the way through with a fully custom implementation and syncing engine. Unfortunately I ran out of time as client work started to pile up. Happy to chat if someone needs a quick 1:1 on my status. But until November I don’t see any time for me to even clone a repo!

rodericj avatar Sep 27 '19 15:09 rodericj

Any updates on this since it's been a few months and many people have some extra time during quarantine? 😉

alexgerrese avatar May 23 '20 17:05 alexgerrese

I have no plans to work on this feature. See my note above. Syncing shared objects is fundamentally different imho. See my note above.

rodericj avatar May 23 '20 19:05 rodericj

Thanks for the update. Our app only has private databases, and we want to allow users to share that database with someone else.

I'm trying to figure out how this would work and it seems like it may be possible to create a SharedDatabaseManager that would use the containers sharedCloudDatabase. Any other changes that would need to be made? For simplicity's sake I would probably make the DB read-only at first.

I would use Apple's UI for adding someone to a database and accepting a share.

kishinmanglani avatar Jul 05 '20 13:07 kishinmanglani

@rodericj any insight would be much appreciated

kishinmanglani avatar Aug 19 '20 21:08 kishinmanglani

The structure of the shared database is quite a bit different than the structure of the private database. For the private database you can simply sync the data. For the shared database there is a concept of a share object, which essentially owns the data item that you are looking to sync. IceCream isn't really build with that in mind. It's quite a change from this architecture. I tried a few years ago and ultimately gave up because I was just chopping at the API making it do things it should do. I've had a few other folks reach out to me and the general takeaway seems to be: "Yes sharing is significantly different than syncing the CloudKit objects. This is such a different paradigm that it requires a completely different approach to the SDK. Sharing CKRecords obviously can be done because it's been in the Apple frameworks for years, but I'm not convinced that this framework is going to be the tool you're looking for to get it done.

That said, If you wish to move forward, just dive in and as a first step, attempt to create a CKShare record. I believe you will find that vanilla CloudKit programming with your own custom sync between the CKShares will be your best bet.

Lastly, I never ended up fully implementing the features I was looking for. I was able to get CKShares "working" but my attempt to tie it to IceCream was convoluted and confusing to the point where I abandoned.

rodericj avatar Aug 20 '20 04:08 rodericj

Thanks @rodericj for the insights provided. Much appreciated. Based on my limited understanding of CloudKit so far, it looks like one should have a private database as well as a shared database to share data. If let's say there are two users A and B using an app with CloudKit integration. A has some data in his app and I suppose this would be in A's private database. Now A wants to share his data with B, this I suppose would be in B's shared database. Is this understanding correct? If that's the case, can IceCream be used still to sync the private database while a custom implementation might be needed to sync the shared database? Any insight on this anyone?

sskjames avatar Apr 01 '21 04:04 sskjames

Maybe? So each user has a private database which is essentially managed by IceCream. Then you implement the shared functionality the way apple wants you to do it, then you sync the shared and the private. Yeah I mean this works, but it sounds to me like you're making something altogether different from ice cream. This is fine, it's just, it's just way different.

I would encourage it!

rodericj avatar Apr 01 '21 05:04 rodericj

Thanks @rodericj for all the thoughts and thank you @caiyue1993 for all the efforts to make this wonderful library.

For the benefit of others who are looking for Realm + CloudKit sharing, I would like to mention that I came across another library called SyncKit and it looks like Sharing is already supported.

sskjames avatar Apr 06 '21 09:04 sskjames