用核心数据 iPhone 实现搜索

Posted

技术标签:

【中文标题】用核心数据 iPhone 实现搜索【英文标题】:implement search with core data iPhone 【发布时间】:2011-11-12 22:20:12 【问题描述】:

我想在我的核心数据数据库中添加搜索功能。 我有一个带有自定义单元格的表格视图,但它们只有 8 个并且不可编辑。 现在,我在 tableView 的 headerView 中添加了一个带有 searchDisplayController 的 searchBar,我想使用 NSFetchedResultsController 来管理搜索数据。 我试图写这段代码,但它不起作用......

-(void)createSearch

    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    searchBar.delegate = self;
    searchBar.scopeButtonTitles = [NSArray arrayWithObjects:@"All", @"Title", @"Notes", @"Tags", nil];
    searchBar.showsScopeBar = YES;
    self.tableView.tableHeaderView = searchBar;
    [searchBar setBackgroundImage:[UIImage imageNamed:@"navbarBg"]];

    searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    searchController.delegate = self;
    searchController.searchResultsDataSource = self;
    searchController.searchResultsDelegate = self;


-(NSFetchedResultsController *)searchResultsController

    if (searchResultsController != nil)
    
        return searchResultsController;
    

    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Task"];
    [request setFetchBatchSize:20];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
    NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor];
    [request setSortDescriptors:descriptors];

    NSFetchedResultsController *afrc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    afrc.delegate = self;
    searchResultsController = afrc;

    return searchResultsController;


-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller

    [self.searchController.searchResultsTableView beginUpdates];


-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath

    UITableView *tableView = self.searchController.searchResultsTableView;

    switch(type) 
    
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self tableView:tableView cellForRowAtIndexPath:indexPath] toIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    


-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

    UITableView *tableView = self.searchController.searchResultsTableView;

    switch (type)
    
        case NSFetchedResultsChangeInsert:
            [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    


-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller

    [self.searchController.searchResultsTableView endUpdates];


-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

    NSPredicate *predicate = nil;

    if (self.searchController.searchBar.selectedScopeButtonIndex == 0)
    
        predicate = [NSPredicate predicateWithFormat:@"1=1"];
    
    else if (self.searchController.searchBar.selectedScopeButtonIndex == 1)
    
        predicate = [NSPredicate predicateWithFormat:@"title CONTAINS[c] %@", searchText];
    
    else if (self.searchController.searchBar.selectedScopeButtonIndex == 2)
    
        predicate = [NSPredicate predicateWithFormat:@"notes CONTAINS[c] %@", searchText];
    
    /*else
    
        predicate = [NSPredicate predicateWithFormat:@"tags
    */

    [self.searchResultsController.fetchRequest setPredicate:predicate];

    [self.searchController.searchResultsTableView reloadData];

这些是 tableView 委托和 dataSource 方法:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    if (tableView == self.searchController.searchResultsTableView)
    
        return [[self.searchResultsController sections] count];
    
    else
    
        return 1;
    


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    if (tableView == self.searchController.searchResultsTableView)
    
        id <NSFetchedResultsSectionInfo> sectionInfo = [[self.searchResultsController sections] objectAtIndex:section];
        return [sectionInfo numberOfObjects];
    
    else
    
        return 8;
    


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    if (tableView == self.searchController.searchResultsTableView)
    
        static NSString *SearchCellIdentifier = @"SearchCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SearchCellIdentifier];
        if (cell == nil)
        
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SearchCellIdentifier];
        

        [self configureCell:cell toIndexPath:indexPath];

        return cell;
    
    else
    
        static NSString *CellIdentifier = @"Cell";

        MainTableCell *cell = (MainTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) 
            cell = [[MainTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"accessoryView"]];
        

        [self configureCell:cell fromArray:cellImages toIndexPath:indexPath];

        return cell;
    

为什么它不起作用?

非常感谢;)

【问题讨论】:

指定“不起作用”。 我没有收到错误,但是当我尝试写一个字母或一个单词时,会显示所有任务,而不是使用谓词过滤的任务 【参考方案1】:

在您调用 reloadData 之前的 searchBar:textDidChange: 消息的末尾:

[searchResultsController 发布]; searchResultsController = nil;

【讨论】:

是的,我阅读了您的回答,但在我的情况下,我不需要两个 NSFetchedResultsController 因为我只使用它来执行搜索。 您是否尝试过破解您的 FEC,然后在您构建 FRC 的位置应用谓词。构建 FRC 后,您只能更改几项内容。 不,我没试过,但我不太明白你想说什么......你能解释一下吗?谢谢;)

以上是关于用核心数据 iPhone 实现搜索的主要内容,如果未能解决你的问题,请参考以下文章

像 iPhone 通讯录应用一样的核心数据搜索?

iPhone核心数据预设

为 iPhone 应用程序实现搜索建议

核心数据(SQLite/iPhone)——设计注意事项?

如何提高 iPhone 上的核心数据获取性能?

iPhone测试中的核心数据问题