将过滤器应用于NSFetchedResultsController

时间:2013-03-12 19:39:44

标签: objective-c uitableview core-data filter predicate

以下工作用于显示表格中的“引脚”列表,我可以使用动作表成功更改_category。

我想只显示与给定类别(即Travel)匹配的结果,但仍然能够将不具有相同类别(即Home)的Pins添加到managedObjectContext。

我尝试了很多方法来使用谓词来过滤所获取的数据(通过将_category与Pin的'category'属性进行比较)无济于事 - 我所获得的最远的方法仍然显示了我的所有条目,无论其类别如何只允许添加所选类别的引脚。

此代码大部分来自Xcode提供的CoreData / TableView模板。

任何帮助都会非常有用 - 这是我第一次使用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;
}
}

1 个答案:

答案 0 :(得分:4)

在fetchedResultsController方法中,您需要在[fetchRequest setSortDescriptors:sortDescriptors]之后立即向您的提取请求添加NSPredicate *对象;行,然后正常运行您的获取请求。

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

我上面显示的格式是从我的一些代码中复制的,因此它可能不是您正在寻找的EXACT谓词格式。如果您在正确格式化谓词时遇到问题,请在此处查看Apple文档:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html

在SO上还有很多关于格式化谓词的线程。