如何在获取后从NSFetchedResultsController过滤核心数据结果

时间:2013-01-15 06:40:55

标签: objective-c uitableview core-data filter

我正在尝试在UITableView中显示一些与数据库关联的NSFetchedResultsController的点。

问题是我需要按特定位置的距离(无线电)过滤结果。我读到计算距离的NSPredicate是不可能的,所以我通过与坐标的简单比较得到了位置周围区域的所有斑点。这给了我一个围绕位置的广场。然后,我想迭代fetchedObjects的结果并删除那些不在区域中的结果。

- (NSFetchedResultsController *)newFetchedResultsControllerWithSearch:(NSString *)searchString{


NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                                            managedObjectContext:self.managedObjectContext
                                                                                              sectionNameKeyPath:sectionName
                                                                                                       cacheName:@"Stores"];
aFetchedResultsController.delegate = self;

NSError *error = nil;
if (![aFetchedResultsController performFetch:&error])
{
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

// ITERATE FETCHED OBJECTS TO FILTER BY RADIO


int n = [aFetchedResultsController.fetchedObjects count];
NSLog(@"Square result count: %i",n);

self.footerLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%i Spots", @"%i Spots"),n];

return aFetchedResultsController;

如何在返回之前从aFetchedResultsController。fetchedObjects中删除对象?它会改变UITableView[fetchedResultsController objectAtIndexPath:indexPath]使用的方法吗?

由于

5 个答案:

答案 0 :(得分:2)

无法修改获取的结果控制器(FRC)的结果集。您可以过滤结果,但如果将FRC用作表视图的数据源,则无效。

可能的解决方案:

  • 预先计算到当前位置的距离,并将距离存储为数据库中的持久属性。然后,您可以直接在FRC的获取请求中使用距离过滤器。当然,最大的缺点是你必须在当前位置发生变化时重新计算距离。

  • 请勿使用提取的结果控制器。执行获取请求并根据半径将获取请求的结果过滤到数组中,并将此数组用作表视图的数据源。这里的一大缺点是你失去了FRC的自动更新功能。每次更改半径或其他搜索参数时,您都必须重新加载表视图。

我知道两种解决方案都不令人满意,但我认为没有一种方法可以将获取的结果控制器与基于函数的过滤器结合起来。

答案 1 :(得分:0)

执行此操作的正确方法是设置包含谓词的新提取请求。获取的结果控制器fetchRequest是只读的,因此您必须将逻辑放入获取的结果控制器本身的延迟初始化中。

if (searchIsActive) {
   fetchRequest.predicate = 
       [NSPredicate predicateWithFormat:
          @"(%K < %@ && %K > %@) && (%K < %@ && %K > %@)",
          @"lat", @(locationLat + limit), @"lat", @(locationLat - limit),
          @"lon", @(locationLon + limit), @"lon", @(locationLon - limit)];
}
else { fetchRequest.predicate = nil; }

然后,要更新表,只需将控制器设置为nil并重新加载

self.fetchedResultsController = nil;
[self.tableView reloadData];

答案 2 :(得分:0)

使用fetchedResultController

NSError *error;

    if (filter) { // check if you need to filter
        // set predicate to self.fetchedResultController.fetchRequest
        self.fetchedResultController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"your filter params"]];
    }else{ 
        // if you dont need to filter and you need to show all objects set predicate to nil
        self.fetchedResultController.fetchRequest.predicate = nil;
    }

    // and perform fetch!
    if (![self.fetchedResultController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

请勿在{{1​​}}

之后忘记更新用户界面

答案 3 :(得分:0)

地理散列。

所以它的字符串有一个你可以做的地方,比如&#39; SQL查询并获取区域周围的结果。

来自维基百科 &#34; Geohash是Gustavo Niemeyer发明的地理编码系统,并被置于公共领域。它是一种分层空间数据结构,它将空间细分为网格形状的桶,这是所谓的Z阶曲线的众多应用之一,通常是空间填充曲线。

Geohashes提供了任意精度等属性,并且可以逐渐从代码末尾删除字符以减小其大小(并逐渐失去精度)。

由于逐渐精确度降低,附近的地方通常会(但不总是)出现类似的前缀。共享前缀越长,两个地方越接近。&#34;

答案 4 :(得分:-1)

使用NSPredicate搜索/过滤数组。示例:

NSString *modelName = @"honda";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"model == %@", modelName];
NSArray *filteredArray = [results filteredArrayUsingPredicate:predicate];