Reputation: 189
The following works to display the list of "Pins" on a table and I can change _category using an actionsheet successfully.
I want to only show results that match the given category (i.e. Travel), but still be able to add Pins that don't have the same category (i.e. Home) to managedObjectContext.
I have tried many ways to use a predicate to filter the fetched data (by comparing _category to the 'category' property of Pin) to no avail - the furthest I've gotten still showed all of my entries regardless of category but only allowed pins of the chosen category to be added.
Most of this code is from the CoreData/TableView template provided with Xcode.
Any help would be incredibly helpful - this is my first time using CoreData.
- (void)setFilter {
//load
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *title = [prefs stringForKey:@"Filter"];
_category = title;
if ([title isEqualToString:@"None"] || title.length < 1) {
title = [NSString stringWithFormat:@"All Pins"];
}else{
title = [NSString stringWithFormat:@"%@ Pins", title];
}
self.navigationItem.title = title;
[self.tableView reloadData];
}
///////////////////////////////////////////////////////////////////////////
//
// Action Sheet
//
///////////////////////////////////////////////////////////////////////////
- (IBAction)showCategorySheet:(id)sender {
UIActionSheet *popupQuery;
popupQuery = [[UIActionSheet alloc] initWithTitle:@"Category" delegate:self cancelButtonTitle:@"All" destructiveButtonTitle:nil
otherButtonTitles:@"Family", @"Friends", @"Home", @"Work", @"Travel", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleDefault;
[popupQuery showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *filter;
if (buttonIndex == 0) {
//Family
filter = @"Family";
}else if (buttonIndex == 1) {
//Friends
filter = @"Friends";
}else if (buttonIndex == 2) {
//Home
filter = @"Home";
}else if (buttonIndex == 3) {
//Work
filter = @"Work";
}else if (buttonIndex == 4) {
//Travel
filter = @"Travel";
}else if (buttonIndex == 5) {
//None
filter = @"None";
}
//save
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:filter forKey:@"Filter"];
[self setFilter];
}
///////////////////////////////////////////////////////////////////////////
//
// Table
//
///////////////////////////////////////////////////////////////////////////
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// The table view should not be re-orderable.
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = object;
}
}
///////////////////////////////////////////////////////////////////////////
//
// Data Handling
//
///////////////////////////////////////////////////////////////////////////
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Pin" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"object: %@", [object valueForKey:@"category"]);
NSLog(@"filter: %@", _category);
//time
NSDate *now = [object valueForKey:@"creationDate"];
NSString *formattedTime = [NSString stringWithFormat:@"%@", [self formattedDate:now type:@"date"]];
cell.textLabel.text = [[object valueForKey:@"pinName"] description];
cell.detailTextLabel.text = formattedTime;
if ([[object valueForKey:@"pinPictureThumb"] description].length > 0) {
NSData *data = [object valueForKey:@"pinPictureThumb"];
UIImage *img = [[UIImage alloc] initWithData:data];
cell.imageView.image = img;
}else{
cell.imageView.image = nil;
}
}
Upvotes: 1
Views: 1740
Reputation: 1876
In your fetchedResultsController method you need to add an NSPredicate* object to your fetch request right after your [fetchRequest setSortDescriptors:sortDescriptors]; line and then run your fetch request normally.
NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"category=%@", categoryToFind];
[fetchRequest setPredicate:fetchPredicate];
The format I show above is copied from some code of mine, so it may not be the EXACT predicate format you are looking for. If you are having trouble formatting the predicate correctly, check out the apple docs here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html
There are also a bunch of threads on SO about formatting predicates.
Upvotes: 4