patternMinor
Using NSPredicate with NSFetchRequest in a NSFetchedResultsController
Viewed 0 times
nsfetchedresultscontrollerwithusingnspredicatensfetchrequest
Problem
I am learning CoreData and I wanted to have my code reviewed. As usual, I get something to work, then I attempt to refine it.
I have a data model that consists of an Item entity and a subItem entity. The Item has a 'to many' relationship with the subItem and subItem has a 'to one' relationship with Item. Basically Item can have multiple subitems, but subitem can only be tied to one Item. My initial tableview displays the items and selecting a row segues to a tabbarcontroller that consists of other controllers, one being another tableview. That tableview displays the subitems of the Item. This is the code I have in my viewDidLoad:
I have a data model that consists of an Item entity and a subItem entity. The Item has a 'to many' relationship with the subItem and subItem has a 'to one' relationship with Item. Basically Item can have multiple subitems, but subitem can only be tied to one Item. My initial tableview displays the items and selecting a row segues to a tabbarcontroller that consists of other controllers, one being another tableview. That tableview displays the subitems of the Item. This is the code I have in my viewDidLoad:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *subItemEntity = [NSEntityDescription entityForName:@"KFPSubItem" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:subItemEntity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"item = %@", self.record];
//add sort descriptors
[fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]];
//initialize fetchedresultscontroller
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
//configure fetched results controller
[self.fetchedResultsController setDelegate:self];
[self.fetchedResultsController.fetchRequest setPredicate:predicate];
//perform Fetch
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
NSLog(@"Unable to perform fetch");
NSLog(@"%@, %@", error, error.localizedDescription);
}Solution
The entity and the sort descriptors of
So while calling the setter methods still works
you should use the "dot-Syntax" for properties:
and the same applies to the properties of
The creation of the fetch request can be simplified with the
factory method
I usually assign the sort descriptors to separate variables first. This may
be a matter of taste, but it avoids too long statements if there is more
than one sort descriptor:
The
line is extremely long and should be split into several lines.
The correct way to check for success or failure of Cocoa (Touch) methods is
documented in
"Handling Error Objects Returned From Methods" in the "Error Handling Programming Guide":
Important: Success or failure is indicated by the return value of the
method. Although Cocoa methods that indirectly return error objects in
the Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO, you should
always check that the return value is nil or NO before attempting to
do anything with the NSError object.
So instead of
you should do
Putting it all together:
NSFetchRequest are defined as "properties"@property(nonatomic, strong) NSEntityDescription *entity;
@property(nonatomic, strong) NSArray *sortDescriptors;So while calling the setter methods still works
[fetchRequest setEntity:...];
[fetchRequest setSortDescriptors:...];you should use the "dot-Syntax" for properties:
fetchRequest.entity = ...;
fetchRequest.sortDescriptors = ...;and the same applies to the properties of
NSFetchedResultsController.The creation of the fetch request can be simplified with the
factory method
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"KFPSubItem"];I usually assign the sort descriptors to separate variables first. This may
be a matter of taste, but it avoids too long statements if there is more
than one sort descriptor:
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetchRequest.sortDescriptors = @[sortByName];The
self.fetchedResultsController = [[NSFetchedResultsController alloc] ...line is extremely long and should be split into several lines.
The correct way to check for success or failure of Cocoa (Touch) methods is
documented in
"Handling Error Objects Returned From Methods" in the "Error Handling Programming Guide":
Important: Success or failure is indicated by the return value of the
method. Although Cocoa methods that indirectly return error objects in
the Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO, you should
always check that the return value is nil or NO before attempting to
do anything with the NSError object.
So instead of
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) { ... }you should do
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) { .... }Putting it all together:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"KFPSubItem"];
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetchRequest.sortDescriptors = @[sortByName];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"item = %@", self.record];
fetchRequest.predicate = predicate;
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController.delegate = self;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unable to perform fetch");
NSLog(@"%@, %@", error, error.localizedDescription);
}Code Snippets
@property(nonatomic, strong) NSEntityDescription *entity;
@property(nonatomic, strong) NSArray *sortDescriptors;[fetchRequest setEntity:...];
[fetchRequest setSortDescriptors:...];fetchRequest.entity = ...;
fetchRequest.sortDescriptors = ...;NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"KFPSubItem"];NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetchRequest.sortDescriptors = @[sortByName];Context
StackExchange Code Review Q#77601, answer score: 5
Revisions (0)
No revisions yet.