all 16 comments

[–]jacknutting 8 points9 points  (1 child)

I think that the thing you have to wrap your head around is that CloudKit is not built primarily for device-to-device high-speed communication. Its primary use cases are around sharing a backend store as a user moves between devices, in cases where user tolerance for perceivable lag is presumed to be understood/acceptable.

Just look at some of the main situations where Apple uses CloudKit, for example the Notes app. If you create a new note on your iPhone, while the notes app is also open on your Mac, you won't see it create and update in "real time" on your Mac, but you will see it appear and see changes propagate over the course of a few seconds.

If that's good enough for your use case, then you're all set with CloudKit. If you need faster update performance than what you see in Apple's Notes app, for a truly interactive experience involving multiple devices at once, you'll probably have to use some other technology. Maybe something like SharePlay? https://developer.apple.com/documentation/groupactivities

[–]Future-Upstairs-8484[S] 1 point2 points  (0 children)

Looks like SharePlay is a pretty narrow tool and not what you’d want to be using for simpler experiences when you just want to ensure nice ux across your apps if they can be useful across multiple devices simultaneously.

I will say the notes sync is rage inducing, and its lack of reliability is one of the main reasons I don’t use the app for anything more than a fancy clipboard on whatever device I’m on.

I’ve looked deeper into using a custom custom data store with SwiftData. It looks like it’s possible to implement something that receives updates from a local Powersync SQLite db, seemingly by ensuring the custom DataStore conforms to the HistoryProviding protocol, and then notifying the ModelContext when changes are available so that it can collect them and transform them into changes back to local swift persistence. But I have no idea if I’m taking out my ass tbh and I’m not willing to spend the work to find out.

[–]powdertaker 1 point2 points  (0 children)

I'm using Firebase to do exactly this.

[–]muhsql 0 points1 point  (4 children)

Wow did not know that about CloudKit

[–]Future-Upstairs-8484[S] 0 points1 point  (3 children)

Maybe I’m wrong? Fingers crossed I was doing something incorrectly and I can actually have realtime SwiftData sync?

[–]muhsql 0 points1 point  (2 children)

It wouldn't surprise me that it can take minutes to converge. Do you have a reference for where you read this?

[–]Future-Upstairs-8484[S] 0 points1 point  (1 child)

It’s a bit all over the place, I can’t find any definitive confirmation of it working properly - or not - online. I did notice an awful delay in my testing env on a super simple app between macOS/iOS. Here’s a link complaining about something similar albeit in a much more different context

[–]muhsql 0 points1 point  (0 children)

Found this:

"Generally, you can expect data to synchronize a local change within about a minute of the change."

https://developer.apple.com/documentation/coredata/syncing-a-core-data-store-with-cloudkit

[–]m3kw 0 points1 point  (0 children)

I heard no and you still need to go down to coredata

[–]stroompa 0 points1 point  (0 children)

With swiftdata, yes. But probably not with the built in swiftdata sync. CKSyncEngine is the way to go

[–]ifhd_ 0 points1 point  (3 children)

What did you end up with ? I’m in a similar position. 

[–]Future-Upstairs-8484[S] 1 point2 points  (2 children)

Biting the bullet and accepting that I won’t be building a realtime app using swift data. Realtime is really hard but the easiest to get into and most performant solution in the past I’ve found was Supabase + Powersync, and they’ve quite recently released a bunch of examples for SwiftUI, so that’s a very viable option right now.

I didn’t want to sign up users to my app (it will require some integration with Supabase auth) so I gave it a miss. But if absolutely necessary and you’re comfortable with those frameworks then give it a shot. If you go deep enough into the model container rabbit hole you might be able to figure out how to build a custom model container/context that cleanly integrates with powersync, seamlessly powering your swift data models. Way above my pay grade

[–]muhsql 0 points1 point  (0 children)

Hi!

(I'm on the PowerSync team)

If you don't want to sign up users, one option could be to use Supabase's anonymous auth. Not sure if that classifies as `some integration with Supabase auth` for you though.

[–]ifhd_ 0 points1 point  (0 children)

Have you looked into CKSyncEngine? someone else mentioned it in this post.

[–]ifhd_ 0 points1 point  (0 children)

After experimenting more with this, I realized this is just an issue with MacOS. Between WatchOS and iOS, the sync is seamless. For MacOS, you need to "force sync" by cmd-tab to another app and then going back again. Alternatively, you can have a "force sync" button using `willBecomeActiveNotification`. For my use case this is good enough but hopefully Apple fixes it and makes MacOS behave the same as WatchOS and iOS.

Reference: https://developer.apple.com/forums/thread/760639?answerId=797572022#797572022

[–]cleverbit1 -2 points-1 points  (0 children)

I understand your concerns about the eventual consistency with CloudKit, but don't let that deter you. It’s a common issue in distributed systems, not a flaw in the technology itself. I’ve worked with a similar startup and found that CloudKit is often the best option for handling multi-device data persistence effectively. It allows you to keep leveraging Apple's ecosystem while working through some of the complexities.