2013-03-12 3 views
1

Следующие работы отображают список «Pins» на таблице, и я могу с легкостью изменить _category, используя таблицу действий.Применение фильтра к NSFetchedResultsController

Я хочу показывать только результаты, соответствующие данной категории (т. Е. Путешествие), но при этом можно добавлять булавки, которые не имеют одинаковой категории (то есть дома), в managedObjectContext.

Я попытался использовать предикат для фильтрации выбранных данных (путем сопоставления _category со свойством «категория» Pin) безрезультатно - тем более, что я все еще показывал все свои записи независимо от категории но допускаются только добавленные контакты выбранной категории.

Основная часть этого кода относится к шаблону CoreData/TableView, снабженному Xcode.

Любая помощь будет невероятно полезна - это мой первый опыт использования 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; 
} 
} 

ответ

4

В вашем методе fetchedResultsController вам нужно добавить объект NSPredicate * к вашему запросу выборки сразу после [fetchRequest setSortDescriptors: sortDescriptors]; и затем выполните запрос на выборку в обычном режиме.

NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"category=%@", categoryToFind]; 
[fetchRequest setPredicate:fetchPredicate]; 

Формат показывает выше копируется из некоторого кода шахты, поэтому он не может быть EXACT формата предиката вы ищете. Если у вас возникли проблемы с форматированием предиката правильно, ознакомьтесь с яблочными документами здесь: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html

Есть также куча потоков на SO о форматировании предикатов.

+0

Вот что я делал раньше. Это позволяет только добавлять в список столбцы указанной категории. Однако, если у меня есть категория, установленная в «Главная», и я добавляю объект с категорией «Работа», объект никогда не добавляется. Кроме того, при смене категорий мне нужен новый список объектов, которые соответствуют новой категории, и этот код по какой-то причине не делает этого. –

+0

Во-первых, я предполагаю, что «pin» настроен как ваш объект, а категория - это атрибут этого объекта. Это верно? Во-вторых, если предикат не изменяется, вам необходимо NSLog для объекта categoryToFind и убедиться, что он устанавливается правильно всякий раз, когда создается объект предиката. – JiuJitsuCoder

+0

Да, «Pin» - это объект с атрибутом «категория». После добавления NSLog для отслеживания категории в предикате, я обнаружил, что он работает только в том случае, если я покину стол и вернусь. Есть ли способ заставить его работать снова, не делая этого? –

Смежные вопросы