Why does deleteObject: cause CoreData faults? - ios

I have a cleanup routine that purges out a bunch of managed objects, form some reason that seems to trigger a lot of CoreData faults.
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"LogEvent"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"id" ascending:YES];
[request setSortDescriptors:#[sortDescriptor]];
[request setFetchLimit:numberToPurge];
NSArray *events = [context executeFetchRequest:request error:nil];
for (LogEvent *event in events) {
[context deleteObject:event];
}
[context save:nil];
This is what I see in instruments.

This faults are usually fired to update inverse relationships on objects that was linked to deleted objects.

Related

Why CoreData is returning only 20 records?

I am using CoreData in my application. Everything is working fine except coredata is always returning max 20 records although i have more than 50 records. I have checked my code again and again but not finding the exact reason. I am also not using fetchLimit property. Kindly Help me.
Thanks.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_manager.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = nil;
if (key != nil) {
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:ascending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
}
NSError *error = nil;
NSMutableArray *array = [[_manager.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
return array;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSInteger rowCount = [context countForFetchRequest:fetchRequest error:&error];
fetchRequest.fetchLimit = rowCount;
NSArray *allItems = [context executeFetchRequest:fetchRequest error:&error];
Here rowCount will calculate actual count of all rows and you can set it as fetchLimit
Core Data returns 20 records by default. You can set records limit by using setFetchLimit of NSFetchRequest class.
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:[...]];
[request setFetchLimit:50];

Deleting a record from coredata with a where clause

I have an entity(UserDetails) which has two columns (username,password).
for eg:
from this I'm populating distinct values and displaying them on a table view.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"UserDetails"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch:#[#"username",#"password"]];
//not sure if this will generate the same output as what I'm thinking of.
self.users = [[managedObjectContext executeFetchRequest:request error:nil] mutableCopy];
[self.tableView reloadData];
Output expected(from the above code):
(abc,def)
(abc,xyz)
(abc123,def123)
(s01,s01)
Now I want to add a delete feature to the table view which should delete from both table and the core data record.
As they are not populated in the same order as that of the coredata model, I want to delete it using something like a where clause. So whenever I delete (abc,def) it should delete all the similar records in coredata.
can someone help on how to solve this?
TIA
You can do like this:
+(BOOL)deleteDataFromUserDetailsTableWithUserName:(NSString*)strUsername AndPassword :(NSString*)strPassword;
{
AppDelegate *objApDel = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [objApDel managedObjectContext];
NSEntityDescription *userEntity=[NSEntityDescription entityForName:kTableName inManagedObjectContext:context];
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
[fetch setEntity:userEntity];
NSPredicate *p=[NSPredicate predicateWithFormat:#"username == %# AND password=%#", strUsername,strPassword];
[fetch setPredicate:p];
//... add sorts if you want them
NSError *fetchError;
NSArray *fetchedDetails=[context executeFetchRequest:fetch error:&fetchError];
for (self.users *details in fetchedProducts) {
[context deleteObject:details];
}
if (fetchError == nil) {
return YES;
}
else
{
return NO;
}
}
With iOS 9 NSBatchDeleteRequest is available. You can use it to delete objects from CoreData similar to DELETE in SQL using a WHERE clause.
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"UserDetails"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username==%# AND password=%#", #"abc", #"def"];
[request setPredicate:predicate];
NSBatchDeleteRequest *deleteRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *error = nil;
[myPersistentStoreCoordinator deleteRequest withContext:myContext error:&error];
For prior versions you will have to fetch all objects first and then delete them individually. There is no other way.
Also if you are using NSFetchedResultsController you can be notified when those objects get deleted and thus remove them from your UITableView.

FetchRequest not updated with most recent record added to Core Data

Every time my app runs it generates data that is stored in a core data entity "Entity". The result of my fetch request does not update with this most recent data, except if I exit the app and relaunch it again. I thought the "shouldRefreshRefetchedObjects" property would fix this issue but apparently not. My current fetch request code is the following:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entity" inManagedObjectContext:context];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"date_time" ascending:YES];
NSArray *Descriptors = [NSArray arrayWithObject: descriptor];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setShouldRefreshRefetchedObjects:YES];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:Descriptors];
NSArray *historyDataArray = [context executeFetchRequest:fetchRequest error:Nil];

How to fetch data from NSManaged object context

NSFetchRequest *fetchLLObjects = [[NSFetchRequest alloc] init];
[fetchLLObjects setEntity:[NSEntityDescription entityForName:#"CustomerOrder" inManagedObjectContext:self.managedObjectContext]];
[fetchLLObjects setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error = nil;
NSArray *allObjects = [self.managedObjectContext executeFetchRequest:fetchLLObjects error:&error];
Here array is showing nil. But in database I could see that there are data. I don't know what might be the reason.
Please add your predicate in the fetchrequest
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CustomerOrder"
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"managedObjectID == %#", managedObjectID]] inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
Set following 2 properties and you are done.
fetchRequest.returnsDistinctResults = YES;
fetchRequest.resultType = NSDictionaryResultType;
Hope this helps.
Edit
NSFetchRequest *fetchRequest= [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Songs" inManagedObjectContext:myManagedObjectContext];
//Take properties dictionary
NSDictionary *entityProperties = [entity propertiesByName];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsDistinctResults:YES];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:[entityProperties objectForKey:#"song_type"]]];
NSArray * result = [myManagedObjectContext executeFetchRequest:fetchRequest error:nil];
You said: "But in database I could see that there are data."
I'm skeptical of that statement. I suspect that no CustomerOrder objects exist in the Core Data store. The only way to "see" the data inside the store is to turn off journaling mode and use 3rd party software to peak inside the .sqlite file.
Despite what others have said, your fetch request is fine. So double check your code where you insert objects into the store and save to the context.

App Not Pulling Core Data

I have Core Data set up for my app. I ran into a problem with the fetch request, but fixed it by specifying the managedObjectContext being from the appDelegate.
When I do an NSLog, it returns the array count as being 0. Any suggestions on how to debug this? I'm not sure where to start debugging as I'm relatively new.
I know there's data in Core Data, and I think the fetch is going through alright. The entity is named Category, and that's where I'm stuck! Any tips for debugging would be great.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Category" inManagedObjectContext:[appDelegate managedObjectContext]];
[request setEntity:entity];
// Specify how to sort the list
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"cat_name" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"%d",[fetchResults count]);
Thanks!
Simple issue was that I was calling [appDelegate managedObjectContext] in the second l line, but was only calling managedObjectContext for the fetchResults.

Resources