Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Just a few questions #17

Closed
thatvirtualboy opened this issue Aug 25, 2023 · 5 comments
Closed

Just a few questions #17

thatvirtualboy opened this issue Aug 25, 2023 · 5 comments

Comments

@thatvirtualboy
Copy link

Hi and thanks so much for creating this useful tool! I had a view questions I'm hoping you can help me with:

  1. Can you explain a bit more what requirements need to happen in order for "Setup State" to show successful? I ask because I had re-installed my app, successfully re-download all data from iCloud, Import/Export showed Successful but Setup was Not Started. It wasn't until I killed and re-launched that it updated.

  2. I have a user who has just over 100 saved objects on their iPhone in my app, but only 94 are syncing to their iPad. New projects aren't syncing between the two devices, and the status page is reading: Export Failed "CKERRORDOMAIN ERROR 2" -- I can't find much online about this error or what the suggested steps to fix it are. I'm not expecting you to help me troubleshoot, but I'm curious if you've come across this error before and if you've found a successful and repeatable way to address it.

Thanks so much!

@ggruen
Copy link
Owner

ggruen commented Aug 26, 2023

Hi @thatvirtualboy ,

  1. setupState is set to .succeeded(started: startDate, ended: endDate) when NSPersistentCloudKitContainer sends a SyncEvent whose type is .setup and whose startDate and endDate properties are not nil (which in theory means the setup has ended, therefore setup has succeeded). See internal func setProperties(from event: SyncEvent). If setupState is showing .notStarted, it means that CloudKitSyncMonitor didn't receive one or more events from NSPersistentCloudKitContainer. You might have a race condition in which NSPersistentCloudKitContainer is firing events before your app is detecting them with CloudKitSyncMonitor. (NSPersistentCloudKitContainer publishes a stream of events (of type SyncEvent) telling your app what it's doing. CloudKitSyncMonitor listens to those events and turns them into state variables you can check and display; if it misses events, it won't be able to update the variables). You may just need to make sure to set up CloudKitSyncMonitor before NSPersistentCloudKitContainer, although it's been so long since I've done that that I can't remember how.
  2. CKERRORDOMAIN ERROR 2 is a network error - the device can't connect to the network (or, really, it is running into some network-like error when CloudKit is trying to export data). Export errors like this are why I wrote CloudKitSyncMonitor, as iCloud is the "source of truth" for synced data, and the usual fix for errors like this, if it's not something simple like they're not on the Internet or a firewall is blocking outgoing traffic, is to delete and reinstall the app. Yes, that means the 6 items that are not exporting from the iPhone (assuming the iPhone is what's showing the export error) will be lost. I'll pause a moment while you gasp and go through the stages of grief. Your user might be able to go into Settings and turn iCloud Sync off and back on for your app, but I'm pretty sure the local data will be deleted anyway, not merged. With NSPersistentCloudKitContainer, it's critical that data make it up to iCloud, or it doesn't really exist. However, I also haven't run into random export errors like that since iOS 14 (15?) or so, so make sure your users are on new OSes. NSPersistentCloudKitContainer was very buggy at first, having frequent problems with items not syncing; detecting that export error quickly was critical to avoiding data loss. I assume your users are on something newer than iOS 14, but you never know, and it makes a big difference in stability.

@thatvirtualboy
Copy link
Author

@ggruen Thanks Grant so much for the detailed explanation on both items! This is very helpful.
Unfortunately the export errors are still present on current iOS builds, though seemingly less frequent.

At any rate, I really appreciate the reply. Thank you!

@aehlke
Copy link

aehlke commented Mar 13, 2024

You may just need to make sure to set up CloudKitSyncMonitor before NSPersistentCloudKitContainer,

Does this mean that instead of just having an ObservedObject in a view, the sync monitor should also be initialized somewhere in the app delegate before it's actually later used by a view that the user navigates to? The docs don't suggest triggering some behavior before its use in a view. Thanks

@ggruen
Copy link
Owner

ggruen commented Mar 14, 2024

Hi @aehlke,

Good question, and I think there may be a race condition in the design of the module in "normal" use.

Basically, CloudKitSyncMonitor is usually accessed as a singleton (SyncMonitor.shared), but the SyncMonitor instance won't be initialized until that singleton is accessed. So, if CloudKitSyncMonitor is used in a view (as will usually be the case), it's possible that the view won't be initialized before NSPersistentCloudKitContainer starts sending messages, so it could miss a message.

In my code, I use a view model, which is initialized very early in the startup process (I forget where and I've paused my Apple development for the time being so I can't look it up), so I didn't run into problems.

If there is an issue caused by missing early messages, then you can try putting let _ = SyncMonitor.shared before NSPersistentCloudKitContainer is set up (e.g. in the app delegate) and see if that fixes it. That should cause SyncMonitor to subscribe to the notifications before NSPersistentCloudKitContainer can start doing anything.

If you try this, please post your findings here. :)

@aehlke
Copy link

aehlke commented Mar 15, 2024

That's what I ended up doing, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants