Core Data is deleting records when app crashes - ios

I have an app that saves a lot of data in the phone. I am using the following code:
- (void)datostickets:(NSString*)cod local:(NSString*)nombre{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *ticket =[NSEntityDescription entityForName:#"History" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:ticket];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(codigo = %#)", cod];
[request setPredicate:pred];
//NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
NSManagedObject *nuevoticket = [NSEntityDescription insertNewObjectForEntityForName:#"History" inManagedObjectContext:context];
[nuevoticket setValue:[NSString stringWithFormat:#"%#",cod] forKey:#"codigo"];
[nuevoticket setValue:self.idloc forKey:#"actividad"];
[nuevoticket setValue:nombre forKey:#"localidad"];
NSLog(#"GRABA: %#",cod);
} else {
NSLog(#"VERIFICA");
check++;
}}
It saves fine, but the problem happens if the app crashes (I think it only happen this way, also the app only crashes when I am manipulating the data).
When the app crashes Core Data starts acting really weird, and it deletes the recent data that I saved, but somehow some of the old data is not deleted (apparently when I change of viewController Core Data makes a commit, so this old data is not deleted).
This problem is solved when I navigate trough the app windows and it starts again if the app crashes. I know the problem is pretty weird.
So, is there a way to solve this? maybe there is a commit statement or something like that.
Thanks for the help

Use [context save:&error] to commit changes.

Use context save& error .or if you using magicall records use MR_Save to persistent store and wait method other wise it is Unable to delete data from storage.

Related

Check if database is empty in iOS without of calling current NSManagedObjectContext (Core Data)?

My question is similar to the following one but has differences
I use Core Data. The problem is if I use the current NSManagedObjectContext then I may get an incorrect result. For example:
From the beginning the db is filled.
My app deletes all the entities via the current context.
I get check if db filled and get NO but in reality the db is still filled because the context should be saved to apply the changes.
And example of my solution:
- (BOOL)isDBFilled {
//separate context to
NSManagedObjectContext *context = [[[NSManagedObjectContext alloc] init] autorelease];
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[context setPersistentStoreCoordinator:coordinator];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:... inManagedObjectContext:context];
[request setEntity:entity];
[request setFetchLimit:1];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
if (!results) {
LOG(#"Fetch error: %#", error);
abort();
}
if ([results count] == 0) {
return NO;
}
return YES;
}
So is it normal and safe to create another context just to check if db is filled? Or Is there better ways to perform this checking except of creating a separate BOOL variable which will be changed before db changes and after them?
It is fine to use a separate context to check if the database is populated or not. The overhead is minimal, so I would have no objections.
Please note that Apple does not necessarily agree. From the "Core Data Snippets":
Neither should a view controller create a context for its own use (unless it’s a nested context).
That being said, I do not see the need for this. If you delete all entities, save and then check should get an empty database. If you delete all entities and do not save and then check, you should get a non-empty database. You can easily - and more easily - do this with one context.
PS: autorelease seems to indicate that you are using a very old SDK. How about upgrading?

Fetch Data from multiple Entities with no relationship between them

I have to fetch data from multiple entities which are associated to different screens of an iPhone App, now the scenario is as follows, when user press a Sync button i will have to fetch data from all these entities (i have about 12 entities) and send all this data to a server via a web service, and all these entities have no relationship among them, now my question is what is the best approach to do this task, should i write 12 different fetch requests in a single method, or is there some other better approach, if any one can guide with some tutorial link, that will me most appreciated, thanx in advance.
You can use a for loop to accomplish your task like this. I've used this code to delete all entries of the Database.
NSArray *allEntities = [[[[UIApplication sharedApplication] delegate] managedObjectModel] entities];
NSError *error;
for (NSEntityDescription *entityDescription in allEntities)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entityDescription];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Error requesting items from Core Data: %#", [error localizedDescription]);
}
//Do whatever you need to do here
}

core data saving context

I am only seeing the saved context after I restart my app. I have two view controllers, one that allows a user to save a core data record and the other to display. When I save a new record, then go to the table view to see all the records created, I do not see the new record. This is how I create a record:
NSManagedObjectContext *context = [self managedObjectContext];
Property *myProperty = [NSEntityDescription
insertNewObjectForEntityForName:#"Property"
inManagedObjectContext:context];
myProperty.aptDescription = curProperty.description;
NSError *error;
[context save:&error];
[appDelegate saveContext];
And then i retreive it doing this:
ATAppDelegate *appDelegate = (ATAppDelegate *)[[UIApplication sharedApplication]delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Property" inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
self.myProperties = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
But like I said the new object is not shown when I go back into the table view immediately after creating the record. What is the issue?
Sounds like you are not implementing the delegate methods of the NSFetchedResultsController properly. Although you did not share any of your view code so it is impossible to be certain.
In addition, after a save you are not checking the BOOL return from the -save:. You should always, always, always check that BOOL and at least log the error. You could be throwing an error and never know it.

Can not persist the deletion of a record using Core Data

I am using Core Data in a simple table view app which keeps track of a user's exercises. When one record is deleted, the deletion persists across that launch of the app. However, if I close the app and re-open it, the record re-appears. The user can delete the record from a detail view:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"OK"])
{
//delete record from database...
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Parameters" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name like %#", parameters.name];
[request setPredicate:predicate];
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];
for (NSManagedObject *obj in matchingData) {
[context deleteObject:obj];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
else if([title isEqualToString:#"Cancel"])
{
}
}
I can not figure out why the deleted record re-appears. This occurs on the simulator and on the device. I 'reset content and settings' on the simulator but still no luck.
Any suggestions are greatly appreciated. Thanks in advance.
Context is a "scratch pad". The "scratch pad" concept allows you to made changes locally in that "scratch pad", such as modifying the record or deleting the record, and discard the changes if you decide too.
You can also have multiple contexts or "scratch pads", usually one context in each thread, such as one for main thread, and another one for background thread.
Now, if you have decided that the changes are OK, you need to persist the changes by saving the context.
NSError *error = nil;
[context save:&error];
Of course, if you have other "scratch pads" in your app, you will need to sync those changes you have saved in the core data.
Use NSManagedObjectContext's save: method after you're finished doing changes to your Managed Object Models
Hope this helps!

Can not delete an entity from Core Data, using RestKit 0.20

The code below does not delete the entity. The "delete was successful" message appears on the console so the entity is found. All other operations I use succeed.
I am using RestKit 0.20.
NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSError *error = nil;
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity: [NSEntityDescription entityForName:#"Auction" inManagedObjectContext:context]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"AuctionID = %d", auctionID];
[fetchRequest setPredicate:predicate];
NSArray *result = [context executeFetchRequest:fetchRequest error:&error];
if(result.count) {
Auction *block = result[0];
[context deleteObject:block];
BOOL status = [context save:&error];
if (status == NO) {
NSLog(#"delete falied for AuctionID:%d, error: %#", auctionID, error);
}
else {
[context processPendingChanges];
NSLog(#"delete was successful for AuctionID:%d", auctionID);
}
}
Why might this delete operation not succeed and what is the solution to making it work.
I found this solution :
In fact, you have to fetch datas from the persistentstore and not the current created managed context :
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"MyModel"];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"id" ascending:NO];
fetchRequest.sortDescriptors = #[descriptor];
// Setup fetched results
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
// AND TO DELETE A MODEL :
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext deleteObject:myobject];
i am doing the same thing and have nearly same code.
In my code also, i get delete done and saved....
But, its not deleted when i am checking DB.
the problem is not with simulator... SURE bcz i am getting same problem on device also.
there is something called child context, it might be the cause...Check these links http://restkit.org/api/0.20.0-dev/Classes/RKManagedObjectRequestOperation.html#//api/name/managedObjectContext
RestKit 0.20 — What is the preferred way to create a new NSManagedObject?
. If you found solution pls share here
#Sumitiscreative I ran into the same issue today. What if found was that normally using Core Data you have to use
[NSManagedObject save:]
for it to store the changes. I dug through Restkit a bit and found this
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext deleteObject:(NSManagedObject *)];
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext saveToPersistantStore:(NSError *)];
Calling this after the above delete method is working to remove the object out of the DB.
**Edit - Also I would have just made this a comment but i don't have the option
#Lance
Hey, pls update your restkit with the latest version.
As now, this works in the latest version , if your server related configuration is correct. and if you get success codes for your delete request from server. Then, restkit automatically deletes the data.
If you need to delete any data externally then, you can use persistentStoreManagedObjectContext and after deleting, save it.
Also, if you want to check at your end that whether its correctly deleting via restkit or not. what you can do is ...
make delete request, after success
check with same id, if item exists. (just for help)

Resources