How delete from CoreData fast? - iphone

I have an app with some stocks information for example and store it in CoreData. I have two entities Stock(name) and DailyStockData(date,number) and I store two years information for each stock entity. Then user can delete some Stock names in TableView.
In my - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
I delete this Stock and DailyStockData cascade and save context then.
My save code looks like this
// Save the context.
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
The problem is: when User deleting stocks fast - my app crashing. I understand that the reason is "abort" command when my device didn't finish save previous deleting transaction and call to save it again.
So I have two questions here ^)
1. Is there any way to prevent this crash?
2. What is best practice to deal with context save error? May be I can try save it again and again rather than just abort.
The simplest solution is redesign application to save context at the "very" end - for example when my app change view or something but I want to know all possibilities.

You should NOT invoke "save" frequently, it's bad for performance.
The "save" method let the CoreData actually save the modified data to your disk, it takes time if there are a lot of data need to be saved.
Just save once while your App is going to exit or going background is good enough.
If you worry about an unexpected crash will lose some data, you can invoke "save" when your users stop modifying data for a while or exited the edit view in your App. It depend on your decision, but just don't save every time your data is changed.

What i do is, i create the database using CoreData, but i dont use simulator to put in information into the database. I use Navicat lite to put in information into the database. If you want to delete the whole database, just delete it from the simulators folder under user/library/application support/iphone simulator//applications//documents/. That will delete the whole database, unless u have synched with ur application folder.

Is there any way to prevent this crash?
Yes, remove the abort(). The abort is only used in minor example code when you don't want to take the time to log, analyze or respond to errors. You would never use it in real code.
What is best practice to deal with context save error?
The first thing to do is log the error in detail so that you have some idea what is actually failing.
I understand that the reason is "abort" command when my device didn't
finish save previous deleting transaction and call to save it again.
Unlikely. It is almost impossible for UI driven action, which works at human speed, to overload any local computer operation. Saving even several hundred objects in Core Data takes only milliseconds while it takes a human a full second or more to delete a row in the UI. If the crash is happening while the UI is in use, then the error is probably related to the UI e.g. not properly updating the section and row count for the tableview.
Don't guess. Log the save error and find out what is actually happening.

Related

iPhone - keep objects in permanent memory options

I need to save my objects in permanent memory. The option I use right now is that i save my objects in the NSUserDefaults before my app quits and I retrieve them when my app starts running. This approach is not very convenient since I may lose important data in case the application crashes. Is there any way to store my objects, but when a property of an object changes, then this change is saved in the disk automatically? Except for that, there is a danger to mess the objects in ram and the objects in the disk using that architecture.
For example
-> Load objects from memory
-> [object1 setValue:#"5"]
-> Application crashes
After the crash, when the user opens the application, the value #"5" will not be available because I never saved the data.
Is there any alternative so as to make by code more safe and maintainable? CoreData is a good option for this problem , or is it an overhead?
If you need to save data, CoreData is the best. You can save after every change if you need to.
If saving info is so important you might want to figure out what could cause/is causing your application to crash and fix that. No matter how good a solution is if your app is going to randomly crash you'll probably lose some data.
It is really not the best of option to save data instantly when a value changes. It's way too expensive for app performance. You must continue using NSUserDefaults to store the values when app is force closed or entered in background.
Your app is designed by you. It MUST not crash but even if it does, don't worry. Anamolies cannot really be handled.

When to use the save: method of NSManagedObjectContext

The question is quite simple: when should I use the save:(NSError **)error method of NSManagedObjectContext? From what I understand the only thing it does it save changed data to the persistent store. The Xcode template-generated application delegate calls the save: method on applicationWillTerminate, is that sufficient?
Details about my code:
Multi-threaded (doing operations in the background, thus using multiple NSManagedObjectContext's)
I'm using a single NSPersistentStoreCoordinator
Data changed on background threads is merged using mergeChangesFromContextDidSaveNotification:
If you need to know more, please do ask!
I couldn't find a guideline on when to call it, so I decided to ask you all. Thanks in advance for your replies!
You always need to call save: when you want your data to save. You can't always guarantee that applicationWillTerminate will be called. For example, if your application crashes due to memory issues (or due to one of a handful of other things) then this won't be called.
I would save data when the user completes the action that is actually generating the data to save.

difference between save: and processPendingChanges: in CoreData

I have an NSManagedObjectContext, i make a couple of changes to the model and then... to "commit" the transactions, what's the difference between doing:
[context save:&error];
and
[context processPendingChanges];
It seems they both do the same thing.
In a nutshell, processPendingChanges changes the state of the current object graph. save will save the current object graph to disk.
Calling save will call processPendingChanges automatically.
If you think of a text file in a word processor, save is analogous to saving the document to disk.
processPendingChanges is analogous to telling the word processor to update it's internal state of the document after an edit, but without saving to disk. This usually triggers updates to the UI such as updating a displayed word or line count, doing any necessary formatting, etc...
In my experience, for the iPhone, you rarely need processPendingChanges. I believe it is mostly intended for Mac OS X and handling advanced or complicated undo management or updating UI bindings.
For the iPhone, this is usually done to trigger NSFetchedResultsControllers to update table views. Even then, this is somewhat rare. If you aren't sure just stick with save
For more info, go study the difference between NSManagedObjectContextDidSaveNotification and NSManagedObjectContextObjectsDidChangeNotification in the docs.

Approaches to save some NSManagedObjects but not others?

I'm working on a Core Data iPhone app that pulls remote resources from the web into NSManagedObjects and saves them locally.
I want the user to be able to designate which of these objects should be saved. This means that some will be saved, but many should be deleted. However, I might want to save and delete at different times - I'd prefer to save designated objects immediately (in case the app crashes), but still keep around the other objects because they're hanging out in table views and such.
One approach I can think of is to have a different persistent store - one for stuff that will be saved, one for stuff that won't; this way I can save the "should be saved" store at any time. However, I would much prefer to keep objects of the same type in the same domain.
Another approach would be to just save at the very end - negating any ability to recover from a crash. But saving at the end would allow me to parse out any objects that weren't designated "should save".
And that's really what I want - a "shouldSave" method in the NSManagedObject class, or at least a save method that I could fire at select objects. But as far as I can tell, neither of those exist.
So, if anyone has any other suggestions, please let me know! It would be greatly appreciated.
CoreData is not for object serialization, it is an object graph serialization. That is an important distinction. Once you have an NSManagedObject it is associated with a context, and CoreData handles saves at context level since that is the only way it guarantee any sort of object graph consistency. In other words, you can't save individual objects because if they have relationships with other objects you would need to also save those objects and it quickly cascades out to the whole graph.
You seem to be worried about crash recovery. If the app crashed and the user relaunched it would they expect to see just the items they saved, or everything that was on the screen before they crashed? If it is the former you should just delete them at save time and remove them from the users view (with some animation), if it is the later you should commit out everything, and potentially delete the objects you are not interested in at another time.

iPhone Core Data application will terminate save database required?

I have an application that allows you to edit some percentages, however it will only let you commit those changes if the percentages add up to 100. However because the Core Data template includes the save code in the application will terminate. If the user changed something and then exited the application, the item would be of course saved even though it did not add to a 100%.
Therefore I simply decided to comment out the save in the application will terminate. I know the other option would be to use another context for the edit and then merge the changes or setting my context values until the actual save point. However I do not see any harm in commenting out this line, since I save whatever I want in my application when the user clicks the save button, so my question is: is the save on the application will terminate mandatory? what possible consequences could this have?. It is important to note that the application continues to work just fine after commenting this lines (which is what I expected).
Thank you in advance.
-Oscar
You can save whenever you like.
However, you will never know when the app will terminate. Unlike applications on more conventional platforms e.g desktops, the iPhoneOS will terminate your app (from the apps perspective) at random. The only warning you will get will be the applicationWillTerminate message sent to the app delegate. If you don't handle saves there then it is highly likely that at some point, your users will lose data.
I think you should reconsider your design. It sounds like you're putting calculation into the managedobjects that could (1) be handled elsewhere in code or (2) be handled by transient properties. You shouldn't have a condition in which the managedobject can't be saved at the drop of hat. Doing so makes your datamodel utterly dependent on external code for its internal integrity. This causes problem with maintenance, portability and upgrading.
Its not mandatory to save on application will terminate. You can save when ever you feel appropriate for the context of the app.