Core data is not persisting in IOS - ios

I'm having an issue where my core data does not persist sometimes. This is the scenario I'm running. I run the app when I'm not logged in, login, and the app stores some data. I then run the app again, this time as the logged in user, and pull that data. It was all working well until I tried to run the app as if it had been downloaded for the first time. To do this I deleted the app from my phone and ran the above steps. However now no data is pulled from the Core Data. Here are some interesting notes and things I have done to remedy the situations.
1) I know with 100% certainty that the data persists if the app is not being run as if just downloaded.
2) The data occasionally persists when run as if just downloaded, but the minority of the time.
3) When I run the app as if just downloaded and store the data into the Core Data, I do an immediate check to see if the data was stored and it is. When I run it again, however, the data is gone.
I'm refraining from posting code right now just because it's very large and would take a lot of time to shorten for the sake of posting. However if you think it'll be helpful in light of what I have said I will post it.

You state that you save with [document saveToURL:forSaveOperation].
In order to persist Core Data you have to save the context.
[managedObjectContext save:nil];
Make sure you call this with a valid context before you expect your data to be persisted. I suspect you have this in some places but not in all required places. One way to find out is to put a breakpoint on each save statement and check if the saves are called as expected.

Related

Core Data doesn't save the first time

I have a problem with RestKit 0.22 and Core Data for saving. To be sure that the rest of my project doesn't cause the problem, I reproduce it with RKTwitterCoreData in RestKit examples. I simply remove seeding part to start with an empty sqlite database. My app is based on the same concept.
My problem happens the first time I run the app. The app receives the data from twitter and displays it. But if I look at the sqlite database itself, it's empty. When I start the app the second time, the database is filling.
Is it possible for RestKit to save the data at the moment it receives it?
Is it possible that RestKit cache all data before saving them. I though that my problem happened because managedObjectCache in RKManagedObjectStore is set with RKInMemoryManagedObjectCache but I also tried with RKFetchRequestManagedObjectCache and I got the same result.
I also tried to save manually in the success bloc with [[[RKManagedObjectStore defaultStore] persistentStoreManagedObjectContext] save:nil] and that didn't work.
Thank you
RestKit does save the mapping result automatically, and before calling the success completion block.
If you want to check what is in the store, ask the MOC (main thread or persistent store MOC) and check the registeredObjects / run a fetch request.
You should not look at the SQLite file(s). The table structure is a private implementation detail, and if you load the file at the command line with the wrong options you won't necessarily see what you expect.

Duplicating CoreData records with iCloud sync

When core data syncs with iCloud, occasionally all of my records are doubled. I believe this happens on reinstall, where the app has not yet synced data, creates a new data set, and then iCloud syncs and there are double of each record for each model.
Is there a way to prevent this sort of behavior? Right now I'm checking every model on load and data sync for duplication, but this seems messy and hackish.
iCloud transfers data between devices asynchronously, and there can be quite some time between when you add data to the iCloud container, and when it actually gets transferred. Metadata is transferred between devices faster, but even this can be quite delayed.
The reason this is important is that you can never do a test on one device that will guarantee that data has not already been added to iCloud. One device may have seeded data, but not yet begun to upload its files/metadata. At that point, a second device cannot know about the seeded data from the first device.
Apple's advice is to handle this by de-deplicating your data after each merge. Each device just adds its own seed data, and if you find that it has been added twice, you delete half of it, being careful to ensure corresponding objects are deleted on each device.
This approach works, but feels a bit like a hack. An alternative, used in my Ensembles framework, is to supply global identifiers for your objects so that the sync framework can automatically import and merge seed data. That is the approach taken in Ensembles, and it makes seeding data quite a bit easier and less ad hoc.
Trying to use just an iCloud store is folly. Data must be stored both locally and in iCloud, or you will run into serious problems.
Use MagicalRecord if you want core data.

iOS, Core Data and iCloud - switching context

I am creating an app where data needs to be displayed right away from the local datastore. I fire off a background thread when the app starts to determine if iCloud is available.
I looked everywhere and can't find the solution to this: when iCloud becomes available, can I change the "options" on the persistentStore to start using iCloud transactions?
I'm not sure what the proper approach is in this situation. Everything I try causes the application to crash.
Originally I had it so the iCloud checking wasn't in a background thread and the app worked fine, but occasionally timed out.
You have not to know when iCloud becomes available. You just work with data but you don't send them directly to iCloud. iOS does it instead you. So only it knows when and how it should send data.
No, you can't change the options on an NSPersistentStore object once it exists. You can only specify the options when adding the persistent store to the NSPersistentStoreCoordinator. The closest you could get to changing options would be to tear down the entire Core Data stack and start over with different options.
That wouldn't help, though, because:
Even if you have detected that iCloud is available (I'm guessing using NSFileManager, either via its ubiquityIdentityToken or by calling URLForUbiquityContainerIdentifier:), your call to addPersistentStoreWithType:configuration:URL:options:error: might still block for a while. If there's new data available in iCloud, it doesn't start downloading until you add the persistent store, and that method doesn't return until the download process is finished. And sometimes, iCloud just makes that method block for a while for no readily apparent reason.
If you let the user make any changes to the data while using non-iCloud options, those changes will not get automatically sent to the cloud later. Core Data only sends changes to iCloud when the data changes while iCloud is active-- which makes it generate a transaction. You'd have to load and re-save any changes the user made, or those changes would never make it to the cloud.
You have, unfortunately, hit on one of the major stumbling points when using Core Data with iCloud. You can't make the full data store available until Core Data finishes communicating with iCloud-- because your call to add the persistent store doesn't return until then. And you can't do anything to speed up that process. This is just one of the headaches you'll run into if you continue trying to use iCloud with Core Data.
Depending on the nature of your data you might be able to use two data stores, one purely local and one synced via iCloud. You could make the purely local data store available while the iCloud one tries to get its act together well enough to be useful. If you stick with one data store though, you're stuck with the delay.

Dealing with Managed Objects between two MVC's with one database

Current Setup:
MVC-1, onViewDidLoad, creates a Managed Object, fetches data from the Managed Object and updates various UI elements.
MVC-2: Same exact setup. I copied and pasted the same code from MVC-1 into MVC-2.
Issues I am seeing:
After launch and opening MVC-1, all the code is executed without any errors. The ManagedObject is created, the fetch requests on the ManageObjectContext work and the UI is properly updated. However, when switching to MVC-2 it seems that none of the data, that MVC-2 is suppose to fetch, is actually being updated. All the UI Elements in MVC-2 have the same data from the last time the application was launched.
Furthermore, if I launch the application and open MVC-2 first I get the same results, only MVC-1 does not appear to be updated this time around.
What is it that I am over looking? I have explicit saves to the database being made. I am (at least I think I am) creating two different ManagedObjects. Do I need to somehow close one before creating the other? Any advice would be very helpful. Thanks.
Figured it out.
I was saving the MOC, however I was not writing the NSManagedDocument to disk (I am using a ManagedDocument as a container for the Core Data database).
So naturally, when I switched to the MVC-2 I would not have the updated data.
I now save the MOC, write the MD to disk and close the MD at viewWillDisappear.
Thanks for the help gusy.

Core Data delay when switching NSPersistentStore files

I'm developing an app with Core Data that periodically downloads all the data from a webservice. Since the download can fail or be cancelled by the user, I want to be able to roll back to the previous state. I tried undoing the NSManagedObjectContext, but that seemed a bit slow (I have tens of thousands of entities). What I'm doing right now is making a backup of the persistent store file, download the data, and, if the download fails, replace the store file with the backup. This seems to work correctly, except there seems to be a delay after I can fetch entities from the store: if after the download I go immediately to a UITableView that uses an NSFetchedResultsController, I find it empty. If I wait some seconds, everything is ok.
So my question is: has anyone had this kind of delays too? Is there something that can be done to avoid this problem, something that forces everything to be ready, even if it blocks the thread?
I haven't used this setup but I think the delay you are seeing is probably caused by Core Data having to clear all it's caching. Core Data uses If you use a cache with the fetched results controller it will have to test and then delete it's existing cache.
I think the best thing to do is to tear down you Core Data stack and reboot it from scratch. That includes recreating a fresh fetched results controller.

Resources