lhunath / UbiquityStoreManager

Implements Core Data + iCloud, deals with all the nasty stuff and gives you a clean API.
http://lhunath.github.io/UbiquityStoreManager
Apache License 2.0
391 stars 37 forks source link

Never gets MOC #32

Closed lauckstreet closed 10 years ago

lauckstreet commented 10 years ago

My application uses many entities. The primary table is not a good place to put the iCloud switch. It uses a split view on the iPad with a search box. I tried to put a view in the table with the iCloud switch and clear/rebuild buttons along with a search box but that caused problems with the search box. So I also have a settings entity and settings screen where I included the iCloud switch and buttons.

I don't know if this is part of the problem or not. I did add the code shown in your MasterViewController to my split screen MasterViewController for the fetchedresultscontroller and the insertnewobject changing 'Event' to the entity that belongs to my MasterViewController. I also added that code to my SettingsViewController where the iCloud switch is located.

The problem is, the MOC never gets initialized. Here is what shows up in the debug window:

2013-12-08 06:45:22.312 Customer Manager[1098:60b] Starting UbiquityStoreManagerExample on device: Peggy's iPad

2013-12-08 06:45:22.338 Customer Manager[1098:1603] UbiquityStoreManager: Loading store... 2013-12-08 06:45:22.339 Customer Manager[1098:1603] UbiquityStoreManager: Will load local store. 2013-12-08 06:45:22.340 Customer Manager[1098:1603] UbiquityStoreManager: Clearing stores... 2013-12-08 06:45:22.340 Customer Manager[1098:1603] UbiquityStoreManager: Will clear stores. Notifying application to reset its UI. 2013-12-08 06:45:22.450 Customer Manager[1098:1603] UbiquityStoreManager: Loading store: CMDataModel.sqlite 2013-12-08 06:45:22.461 Customer Manager[1098:1603] UbiquityStoreManager: Successfully loaded local store. 2013-12-08 06:45:22.462 Customer Manager[1098:1603] UbiquityStoreManager: Finished loading local store (UbiquityStoreErrorCauseNoError). Notifying application to refresh its UI. 2013-12-08 06:45:22.615 Customer Manager[1098:60b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext' * First throw call stack: (0x18d5e709c 0x19991dd78 0x18d2f56ac 0x100123a4c 0x100122568 0x19059bbd8 0x19059baf8 0x19059b888 0x19059f754 0x19059f25c 0x1001214b4 0x199eec420 0x199eec3e0 0x199eef56c 0x18d5a6d64 0x18d5a50a4 0x18d4e5b38 0x192eb7830 0x1905240e8 0x100144b9c 0x199f07aa0) libc++abi.dylib: terminating with uncaught exception of type NSException

I've tried stepping through the code and it appears that the MOC is being initialized on a different thread than the MasterViewController code. I've tried putting in a While claus where the fetchedresultscontoller is initialized in the MasterViewController to see if a wait can give the MOC time to initialize but that just causes the application to eventually terminate probably because the MOC never gets initialized and things timeout.

Any idea why the MOC never gets initialized and how to fix that? I'd really like to implement iCloud in my application because I have both iPad and iPhone versions and plan to also write an OS X version. My iPad/iPhone versions are specifically set up for iOS 7.

Bob

lhunath commented 10 years ago

This sounds very much like an application issue, but I'll try and give a few pointers anyway:

  1. Threads are danger! Make certain that your MOC is only ever used on the thread it is created for. If your MOC is to be used on the main thread, make it a NSMainQueueConcurrencyType. If it's supposed to do stuff asynchronously, make it a NSPrivateQueueConcurrencyType and be sure to do all actions in perform*Bocks. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html#//apple_ref/doc/uid/TP30001182-SW39
  2. USM loads the store asynchronously. That means you won't have a MOC immediately. Additionally, the PSC can go down at any time, at which point you'll need to unset your MOC and make your persistence unavailable (willLoadStore). Essentially, your application's code needs to be able to handle its MOC being nil without crashing: probably by clearing all data in and making your UI temporarily unavailable, as well as detecting when the MOC either becomes available (non-nil) or unavailable (nil) and reset itself/reload its data as is appropriate.

If your application does not crash, and didLoadStore is never called, re-open this bug.

lauckstreet commented 10 years ago

I guess I’ll have to leave iCloud out of my app because I’m not that knowledgeable of an iOS programmer. What you just said is as clear as mud to me. I have no idea how to do what you said, but thanks for the quick response.

Bob

On Dec 8, 2013, at 9:32 AM, Maarten Billemont notifications@github.com wrote:

This sounds very much like an application issue, but I'll try and give a few pointers anyway:

Threads are danger! Make certain that your MOC is only ever used on the thread it is created for. If your MOC is to be used on the main thread, make it a NSMainQueueConcurrencyType. If it's supposed to do stuff asynchronously, make it a NSPrivateQueueConcurrencyType and be sure to do all actions in perform*Bocks. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/NSManagedObjectContext.html#//apple_ref/doc/uid/TP30001182-SW39

USM loads the store asynchronously. That means you won't have a MOC immediately. Additionally, the PSC can go down at any time, at which point you'll need to unset your MOC and make your persistence unavailable. Essentially, your application's code needs to be able to handle its MOC being nil without crashing: probably by clearing all data in and making your UI temporarily unavailable, as well as detecting when the MOC either becomes available (non-nil) or unavailable (nil) and reset itself/reload its data as is appropriate.

If your application does not crash, and didLoadStore is never called, re-open this bug.

— Reply to this email directly or view it on GitHub.

lhunath commented 10 years ago

Keep in mind that this has nothing to do with iCloud but everything with Core Data. That means that even if you leave iCloud out of your app and continue to use just Core Data, you'll still have to follow the above advice.