1

我有一个 CoreData 模型,如下所示:

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

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

===埃及===
开罗
亚历山大
Luxur
Ra​​s AlBar

.

===卡塔尔===
多哈

.
.

现在我有 UISearchBar 应该允许用户根据国家名称或城市名称中输入的单词的存在来过滤 TableView

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

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

.
.

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

4

1 回答 1

2

你应该NSFetchedResultsController为此使用一个。您没有提及您是否是,但它可以更容易地显示CoreDataTableView.

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

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

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

NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubPredicates:@[cityPredicate, countryPredicate]];

然后,当您使用compoundPredicatefetch 时,您将获得所需的内容。

如何设置你的 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];

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

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

于 2013-01-29T17:24:45.453 回答