CoreData: fetch only last elements, not all (iPhone) - core-data

Welcome
i use Core Data to store datas. i need such a method which returns only the last 7 elements of entity. my question is how should i modify this code ( it fetchs all of elements, but i need only last 7)
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
NSError *error;
tripArray = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

Define last? Core Data does not have a concept of order internally. If you mean by the farthest away based on your distance property then you can do the following:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[request setFetchLimit:7];
[sortDescriptor release];
NSError *error;
NSArray *tripArray = [managedObjectContext executeFetchRequest:request error:&error];
Note that the addition of the -setFetchLimit: will cause this request to only return 7 results. It will return the "first" 7 based on your sort. So if you want the closest, reverse the ascending: portion of your sort.
-mutableCopy
There is absolutely no point in calling -mutableCopy on the NSArray that is returned from -executeFetchRequest: error:. Adding objects to that NSArray will not add them to Core Data and removing them from that NSArray will not remove them from Core Data. Therefore it has absolutely no value and is just wasteful.
Do you remember where you saw that? I have been trying to track it down for a while now.

Related

Fetching set of NSManagedObjects using attribute

How does one fetch a set of unique managed objects by requesting a specific attribute to be checked.
e.g. A number of people objects and I would like to retrieve all the unique names, one managed object for each unique name, sorted by name.
What about using a request like this
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Person" inManagedObjectContext:managedObjectContext];
request.entity = entity;
request.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:#"name"]];
request.returnsDistinctResults = YES;
request.resultType = NSDictionaryResultType;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptors]];
NSError *error = nil;
NSArray *distinctResults = [managedObjectContext executeFetchRequest:request error:&error];
// Use distinctResults
Try and let me know.
P.S. Code is ARC enabled. If you are not using it, call release when necessary.

Core Data Sort Descriptors with relationships between Entities

I have two entities, Job and Client. The relationship from job to client is called clientOfJob which is a many-to-one relationship:
Job<<-->Client
I am trying to understand how I would sort my fetch results into sections for the table view, with the sections based on client first names.
This is my first attempt to use sectionNameForKeyPath, but I am using sample code from CoreDataBooks, and so far, substituting some of that code has eliminated some serious problems I had earlier today.
Here is the code I tried. I didn't think it would work, but I'm not sure what I need to use for the client sort descriptor key and for the sectionNameKeyPath.
By the way, the code works well with only the jobSortDescriptor (without the clientSortDescriptor) and with sectionNameKeyPath set to nil. Then it just sorts by job description. I can get at the related client entity information, putting client name information into the detailedTextLabel of each cell while I have the job description in the textLabel of the cell.
- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:10];
NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"clientOfJob.firstName" ascending:YES];
NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"jobDescription" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:dataInterface.managedObjectContext sectionNameKeyPath:#"clientOfJob.firstName" cacheName:#"Jobs"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[jobSortDescriptor release];
[clientSortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved Error %#, %#", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}

NSSortDescriptor is not working while fetching records from Core Data

I am trying to use NSSortDescriptor in Core Data to fetch my records. Array of modal-objects doesn't get affected by sort descriptor. It gives records in same order.Here is my code:
NSManagedObjectContext *moc=[self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"To_Do" inManagedObjectContext:moc];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"repeatDate" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[sortDescriptor release];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
NSError * error = nil;
NSArray *arrEntity = nil;
arrEntity=[moc executeFetchRequest:fetchRequest error:&error];
The code looks fine and should work. Since it does not there a couple of possible causes.
The unsorted fetch order might be the same as sorted order. This can happen sometimes if you create objects in series and use a a key like a creation date or the like.
Your keys might all have the same value. This can happen if you have a default value.
You have the wrong key or misspelled its name. You should get a complaint but it won't crash if it can't find the key.
I had same problem if I had done like this
fetchRequest.sortDescriptors.append("key")
But if I use
fetchRequest.sortDescriptors = ["key"]
Then it works fine

NSPredicate for an NSManagedObject's string attribute's length

Could someone please help me define a predicate that returns only NSManagedObject's who's "letters" attribute length is within a certain range?
Here's the example I've been trying, I've got a feeling it's the letters.length notation, I've also tried the kvc letters.#length with no success.. What am I doing wrong?
NSManagedObjectContext *context = ...;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Word" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"letters" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"letters.length BETWEEN %#", [NSArray arrayWithObjects: [NSNumber numberWithInt:5], [NSNumber numberWithInt:20], nil]];
[fetchRequest setPredicate:predicate];
NSUInteger limit = 20;
[fetchRequest setFetchLimit:limit];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
Not sure how this code snippet is performance wise but here is my answer to your question:
NSString *attributeName = #"letters";
NSString *attributeValue = [NSString stringWithFormat:#"'.{%d,%d}'", 5, 20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K MATCHES %#", attributeName, attributeValue];
[fetchRequest setPredicate:predicate];
Joss.
I've got some bad news. You can't do this. There is no length attribute for strings in the NSPredicate (that I've been able to find).
What I would recommend you do is add an attribute for the length of the stored string in your managed object that gets set when you set the letters attribute. You can then do your query on that attribute and return the values you want.
In case someone is looking for a way to test whether a string has length using an NSPredicate,
it is possible.
Swift:
returns strings with 4 to 7 characters.
NSPredicate(format: "text MATCHES %#", ".{4,7}")

Core Data NSSortDescriptor causing memory leak

I am getting a memory leak when I add a sort descriptor to my Fetch Request in Core Data. If I comment out the NSSortDescriptor block it runs without a memory leak in Instruments.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Pools" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"game.league.id=%i",[lid intValue]];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"game.date" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
// Do Something
[fetchRequest release];
[items release];
Any ideas?
In the sort descriptor, you're walking a relationship using the keypath game.date.
Your leak is probably associated with one of those objects in the keypath. It disappears when you remove the sort because then the objects in the key path don't do anything.
If you have transient properties, custom accessors, non-entity properties etc in the game entity I would look there. Custom value transformers are also a good bet.
The stack in Instrument should tell you exactly which object is leaking.

Resources