Looks like the CloudKit sync issue in *OS 26.4 is real (I can repro with all of my apps), and has the very distinct potential to lead to catastrophic data loss and/or sync conflicts across effectively all apps. Apps only receive changes from the cloud after being quit and relaunched.

If Apple hasn't pulled 26.4 already, it should do so immediately until there's a fixed build

https://mastodon.social/@lukaskubanek/116299581006179836

@stroughtonsmith I tend to disagree. Error handling is mandatory for an app using CloudKit and I can’t see how it could lead to “catastrophic data loss”. Remote notifications have never been reliable. This is a best effort service?
@slizeray @stroughtonsmith I also don’t see how it can lead to data loss because apps should handle duplication / conflict resolution when using CloudKit. But the current issue leads to bad user experience because apps just don’t have any idea of it and people will see their apps out of sync.
@alpennec @stroughtonsmith What is difficult to understand is that Apple explains to developers how to test their applications but that they themselves are unable to avoid catastrophic regression bugs.
I have already experienced catastrophic regression bugs with HealthKit and MapKit. It was eventually fixed with MapKit, but not with HealthKit…
@alpennec @slizeray there's a lot of things that CloudKit developers 'should' be doing that CloudKit developers aren't doing because developing CloudKit apps is way harder than it needs to be. If you think everybody using CloudKit has robust merge conflict support, I have a bridge to sell you
@stroughtonsmith @alpennec CKSyncEngine has greatly simplified the integration with CloudKit and the error handling though. It was way more difficult before, I would say almost impossible before.
@slizeray @alpennec last I heard, people were still recommending to avoid CKSyncEngine. I just saw @bigzaphod remove it from Tapestry last week. I've long-fingered it for years myself because nobody had a glowing recommendation to give it
@stroughtonsmith @alpennec @bigzaphod oh I just see the reason. There are several issues here.
The first one is not related to CKSyncEngine but to the replay API of CloudKit.
The second one is that you have options when fetching changes to fix this issue (Scope + prioritizedZoneIds) but it is supposed you designed your schema accordingly. And it didn’t exist with CKFetchRecordZoneChangesOperation only with CKSyncEngine…
The third issue is that you can’t use ZoneOptions.desiredKeys
@stroughtonsmith @alpennec @bigzaphod So I agree, there is room for improvement with CKSyncEngine. I filed a feature request yesterday… I have no reason to think that anyone at Apple will pay attention though.
@stroughtonsmith @alpennec @bigzaphod The Feedback filed under FB22338675 asks to extend CKSyncEngine.FetchChangesOptions.Scope with a new case case allExcludingRecordTypes([CKRecord.RecordType]) so you can migrate records to new Zones and ignore the old ones…
@stroughtonsmith @slizeray I'm aware we have to do this merge conflict but I intentionally skipped this for my apps... But it depends on the app and the data model though. But it's a rabbit hole just to do it correctly with change tracking at every level (like they suggest in one of their old WWDC video).
@alpennec @stroughtonsmith @slizeray I'm doing record-level last modified wins (based on system clock). I know it's not technically perfect, but you're totally right it's a real rabbit hole to do something more elaborate.
@slizeray anybody using last-write-wins for anything could lose days of work, since iOS apps don't quit

@stroughtonsmith @lukaskubanek FWIW, the game I'm developing, up until 26.4, would sync every move across all devices almost immediately. It was amazing and actually became needed for me to include tvOS support.

Now on 26.4, iCloud ~maybe~ works to leave the game in the state it was in so you can continue elsewhere, but even that's not reliable. Spent way too much time on this to only shrug and stop.

@stroughtonsmith it’s still being offered to me in the UK. Not a good look at all. 😬
@stroughtonsmith @marcoarment @lukaskubanek good thing all of us Liquid Glass hold-outs just got forced on to iOS 26.4 to have a reasonably secure phone
@stroughtonsmith meanwhile a build of my app took 25 business days to reject because "the [iCloud share with user] button isn't responsive" 😂 I'm still not sure what they meant but I added an animation. That was two weeks ago.

@stroughtonsmith @lukaskubanek My test cases:
between TextEdit on macOS 15.7.4 and iA Writer on iOS 26.4 syncs fairly quickly in both directions.

Then looked at iPadOS 26.3.1 iA Writer and it didn't update until I closed the app and restarted.

After that changes on the iPad sync'd to the Mac and not iOS 🤦‍♂️

After closing on my iPhone all 3 sync now.

Wild! Is there QA at Apple?

@stroughtonsmith Glad I’ve so far managed to avoid 26 on all my devices. The litany of bugs on top of all the features that were never delivered just really makes me wonder why Apple keeps forcing the yearly update cycle.
@stroughtonsmith I’ve already filed a bug report with Apple and also shared additional details in the Apple Developer Forums: https://developer.apple.com/forums/thread/820550
iCloud Sync not working with iPhon… | Apple Developer Forums

@stroughtonsmith @lukaskubanek It’s fixed in iOS 26.5 beta as per our internal testing with our apps, FYI.
@gedeonm @stroughtonsmith @lukaskubanek Do Apple’s automatic CloudKit integration APIs really only rely on those notifications? I have one app with my own CloudKit sync, and two with my own CKSyncEngine implementations, but all have a polling component, and hooks in things like didBecomeActive as a back stop, so it’s not ideal, but not tragic, if the notifications don’t come.

@agiletortoise @gedeonm @stroughtonsmith There is a polling component, `CKSyncEngine.fetchChanges(…)`, but I’ve had mixed results with it, same as the @pointfreeco folks in their SQLiteData library, which is based on CKSyncEngine: https://github.com/pointfreeco/sqlite-data/discussions/308#discussioncomment-15075494

My understanding is that it relies on remote notifications to work, which is also confirmed in Apple’s sample app README: https://github.com/apple/sample-cloudkit-sync-engine#prerequisites

About SyncEngine.fetchChanges() behavior on macOS · pointfreeco sqlite-data · Discussion #308

Hi, i tried to use syncEngine.fetchChanges() to control changes pulling, it seems does nothing on macOS. The log of that is like this, but it does not really pull the changes: SQLiteData (shared.db...

GitHub
@stroughtonsmith
Would our issue have anything to do with this:
We’ve been using Reminders for years as the simplest mutual shopping list. Need something from the store? Uncheck it. Bought it? Check it.
Need something not on the list yet, add it unchecked.
Since 26.4 several items disappeared from the list that have been on it since we’ve created it. Like “Bread”.
I mean, we had to re-index the search in Reminders before (a terrible regression for many years now), but now items are truly lost.