【问题标题】:Very confusing results returned when filtering with NSPredicate使用 NSPredicate 过滤时返回的结果非常混乱
【发布时间】:2012-01-18 15:37:40
【问题描述】:

使用 NSPredicate 结合 tableview 和 NSFetchedResultsController 上的搜索框的非常奇怪的结果

它应该基于匹配的名称进行过滤...但是,如果我输入任何有效的名称,我会得到一些不正确的结果。如果我输入任何全名,例如“Mike Johnson”或“Kelly Michaels”,我总是会得到与“Angelo Smith”相同的过滤结果。

NSLog 将显示 "名称包含[cd] \"Kelly Michaels\""

但是屏幕上显示的过滤结果只会显示 Angelo Smith?任何想法如何解决这个问题?

如果您需要有关我正在做的事情的更多详细信息,我一直在使用此堆栈帖子中的解决方案 How to filter NSFetchedResultsController (CoreData) with UISearchDisplayController/UISearchBar

- (NSFetchedResultsController *)newFetchedResultsControllerWithSearch:(NSString *)searchString
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

NSPredicate *filterPredicate = nil;

/*
 Set up the fetched results controller.
 */
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Staff" inManagedObjectContext:self.managedObjectContext];

[fetchRequest setEntity:entity];

NSMutableArray *predicateArray = [NSMutableArray array];

if(searchString.length)
{
    NSLog(@"here searchString is %@", searchString);

    // your search predicate(s) are added to this array
    [predicateArray addObject:[NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", searchString]];
    // finally add the filter predicate for this view

    NSLog(@"%@", predicateArray);

    if(filterPredicate)
    {
        filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:filterPredicate, [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray], nil]];
    }
    else
    {
        filterPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray];
    }
}


   [fetchRequest setPredicate:filterPredicate];
...

【问题讨论】:

  • 嗯,它似乎返回了正确数量的结果。即,如果我输入“Mar”,我会得到两个结果。这是有道理的,因为我有两个名字中带有“Mar”的员工。马克和玛丽。然而,名字改为“Angelo”和“Colin”。所以它过滤了正确数量的员工,只是没有显示他们的正确姓名?我需要某个地方的 reloadData 吗?

标签: objective-c ios core-data uisearchbar


【解决方案1】:

除非数据集发生变化,否则我不会在过滤时创建新的 FRC。相反,只需更改谓词并执行另一次获取(在称为 filterContentForSearchText 之类的自定义方法中)

例子:

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{   
    [self filterContentForSearchText:searchText];   
}

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    searchBar.text = @"";
    NSPredicate *predicate = nil;
    [self.fetchedResultsController.fetchRequest setPredicate:predicate];
    [self.fetchedResultsController.fetchRequest setFetchLimit:0];  // 0 is no limit

    [searchBar resignFirstResponder];
    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  //
    }
    [self.myTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

}

- (void)filterContentForSearchText:(NSString*)searchText
{
    NSString *query = searchText;
    if (query && query.length) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@ or department contains[cd] %@", query, query];
        [self.fetchedResultsController.fetchRequest setPredicate:predicate];
        [self.fetchedResultsController.fetchRequest setFetchLimit:100];  // I use 100 because of the large dataset I am working with (4500 records)
    }

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }  
    [self.myTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}

-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self filterContentForSearchText:searchBar.text];
    [searchBar resignFirstResponder];
}

【讨论】:

  • 示例添加到原始答案。如果您有任何问题,请大声喊叫。
  • 有史以来最好的解决方案!因为我花了 2 天时间尝试使用 2 个 FRC 解决搜索问题!谢谢!
猜你喜欢
  • 2013-02-10
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
  • 2020-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多