The real problem here is the combination of iCloud and Core Data (for non-Apple folks, the built-in persistence/object model framework).
In a somewhat simplified way, Core Data is a data store most commonly backed by SQLite. It's used everywhere from your mail app to the Facebook app. It's handy and convenient when it isn't trying to kill you - it's one of the more complex frameworks that Apple ships, and the documentation is extremely poor for it. It also doesn't help that there is a lot of quirky behavior that's more or less tribal knowledge to long-time Apple devs and WWDC attendees, and is has enough concurrency gotchas to fill a container ship.
So, Core Data is not the simplest piece of code to work with from the get-go, and then you pile iCloud on top.
iCloud is conceptually pretty simple - there's a directory on your file system that is replicated to Apple's servers, and back down to each one of your devices. When files change the OS sends notifications to your app informing you of such. If you're using iCloud as a distributed file system (a la Dropbox), it's easy to integrate.
The trouble with this model is that Core Data stores can be in fact quite large. If you have a 30MB database of, say, recipes on your disk, you really don't want to resend the whole thing every time your user alters a row. Apple special-cases Core Data stores in iCloud by sending only deltas, but the implementation is utterly broken:
- There is no baseline state(s). The database is literally the playback of every delta, with no canonical snapshots. Ever.
- iCloud is really bad at sequencing the deltas, especially if (somewhat) concurrent changes are happening. Core Data is also terrifyingly bad at conflict resolution when deltas from different devices don't line up.
- The above points means that it's trivially easy to break your entire database, as your deltas no longer play back to a sane database file. When this occurs there is no way to roll back your database, since there is no concept of a snapshot or last known good state.
- This is compounded by some really horrible API design on Apple's part. When your iCloud database becomes corrupt it fails silently, with absolutely no API that allows one to determine said broken state. Your app literally stops working with none of the OS making a single peep, and no way for you to proactively check your database's state. iCloud seems to print some debug things into your console indicating this failure, but neither your app nor your users have access to it. This manifests in your app (and in tech support requests) as "iCloud just stopped syncing" - your device stops transmitting deltas and simply works off of the last locally-cached good state, all without telling the dev or the user.
- This is further compounded by the fact that the entirety of Core Data+iCloud was rushed out the door. Documentation was non-existent even up to the day the new version of iOS went out to the public. There was literally only one source of information: a thread on the Apple dev forums that Apple engineers would sometimes pop into.
- This is further compounded by the fact that even the Apple engineers themselves seemed to have no idea how to implement an app with iCloud + Core Data. The example code (provided deep, deep within aforementioned thread) made 90 degree turns seemingly every few days. The same sample would have dramatically changing implementations from week to week. The Apple engineers in the thread seemed as mystified as the people trying to use the framework.
- The poor documentation and poor state of sample code, as well as what is IMO a fundamentally broken architecture means that iCloud + Core Data remains a complete nightmare to this day. I think the poor architecture is really the core of this here - while Apple could have provided better docs and better support, I believe the fundamental architecture choices made here means Core Data + iCloud would never have been workable.
- The icing on top of the cake was an extremely egregious bug that existed at launch (unsure now, you couldn't pay me enough money to work with that API ever again). "Okay, so our deltas are completely fucked" you say, "Why don't we just delete the app's entire iCloud bucket and start over?"
A jolly good idea until you realize that a bug in iOS/iCloud means that when you delete an app's iCloud storage "bin", it cannot be recreated by that app, ever again.