【问题标题】:NSPredicate to filter nested CoreData ModelsNSPredicate 过滤嵌套的 CoreData 模型
【发布时间】:2013-01-29 17:19:42
【问题描述】:

我有一个像下面这样的 CoreData 模型:

国家 >> 城市(一对多关系)

作为节/行结构列在 UITableView 中,即

===埃及===
开罗
亚历山大
奢华
拉斯阿尔巴
.
.

===卡塔尔===
多哈
.
.
.

现在我有了 UISearchBar,它应该允许用户根据 Country name OR City name

中输入的单词的存在来过滤 TableView

因此,如果用户插入 'ar',则应显示以下内容:

===埃及===
拉斯阿尔巴
===卡塔尔===
多哈
.
.
.

在 CoreData 中找不到任何最佳查询来实现我想要的。

【问题讨论】:

    标签: objective-c core-data nspredicate


    【解决方案1】:

    您应该为此使用NSFetchedResultsController。您没有提及您是否是,但它可以更轻松地将CoreData 显示为TableView

    无论如何,您的NSFetchedResultsController 的获取应该在城市中。不是国家。 (同样,你不说它是什么,但以防万一)。

    所以你可以使用的谓词是...

    NSPredicate *cityPredicate = [NSPredicate predicateWithFormat:@"name [cd]CONTAINS %@", text];
    NSPredicate *countryPredicate = [NSPredicate predicateWithFormat:@"country.name [cd]CONTAINS %@", text];
    
    NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubPredicates:@[cityPredicate, countryPredicate]];
    

    然后,当您使用 compoundPredicate 进行提取时,您将获得所需的内容。

    如何设置你的 NSFetchedResultsController

    在您的 CountryTableViewController.m 文件中

    1 - 创建属性...

    @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
    @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
    

    2 - 从您的源中获取托管对象上下文...

    self.managedObjectContext = [(AppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
    

    3 - 添加此方法...

    #pragma mark - fetched results controller
    
    - (NSFetchedResultsController*)fetchedResultsController
    {
        if (_fetchedResultsController != nil) {
            return _fetchedResultsController;
        }
    
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"City"];
        [request setFetchBatchSize:20];
    
        NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"country.name" ascending:NO];
    
        [request setSortDescriptors:[NSArray arrayWithObject:sd]];
    
        NSFetchedResultsController *aController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"country.name" cacheName:nil];
    
        aController.delegate = self;
        self.fetchedResultsController = aController;
    
        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
        return _fetchedResultsController;
    }
    

    4 - 对于过滤表格的方法...

    - (void)filterResultsWithText:(NSString*)text
    {
        NSPredicate *cityPredicate = [NSPredicate predicateWithFormat:@"name [cd]CONTAINS %@", text];
        NSPredicate *countryPredicate = [NSPredicate predicateWithFormat:@"country.name [cd]CONTAINS %@", text];
    
        NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubPredicates:@[cityPredicate, countryPredicate]];
    
        [self.fetchedResultsController.fetchRequest setPredicate:compoundPredicate];
    
        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error]) {
            // Handle error
            //exit(-1);
        }
    
        [self.tableView reloadData];
    }
    

    5 - 显示数据

    这将设置您的数据,您不再需要任何数组。

    要显示它,您可以这样做...

    - (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];
    }
    
    - (NSString*)tableView:(UITableView*)tableView titleForSection:(NSInteger*)section
    {
        id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
        return [sectionInfo title];
    }
    

    要在索引路径上获取国家/地区,您可以这样做...

    Country *country = [self.fetchedResultsController objectAtIndexPath:indexPath];
    

    这将返回该索引路径处的国家/地区。

    有一点需要设置,但一旦你完成了,你就会明白为什么它如此简单。

    【讨论】:

    • 这样我会得到一个 NSArray of Cities.. 但不幸的是我的 UITableView 结构是基于 Array of countries,每个国家(NSManaged)里面都有城市。
    • 就像我说的,你应该使用 NSFetchedResultsController。使用“国家”的sectionPath。然后,您会将部分作为国家,将行作为城市,而不是 NSArray。我会发布一些代码来解释......
    • 编辑了我的答案以解释执行此操作的最佳方法。每当您在 TableView 上显示 CoreData 信息时,您确实应该使用 NSFetchedResultsController。它使显示信息变得非常容易。
    • 您的解决方案看起来很棒!但是现在你让我陷入了另一个问题,那就是如何将你的解决方案映射到 RestKit!有什么想法吗?
    • 不确定你的意思。你能在你原来的问题中解释一下吗?我会尽力帮忙的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多