我发现了BSFetchedResultsController github 项目,它是一个 NSFetchResultsController 子类,它执行 Martin 建议的操作,它使用任意排序描述符在内存中排序,此外,它还注册上下文更改并再次计算任何索引更改,同时考虑到任意排序描述符. 总而言之,这是一个非常令人印象深刻的壮举!我成功地使用它按距离排序,如下所示:
BSFetchedResultsController* fetchedResultsController = [[BSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// create a location to compare distance to, e.g. current location
CLLocation* sourceLocation = [[CLLocation alloc] initWithLatitude:55.87595153937809 longitude:-4.2578177698913855];
// compare the distance from both to the source location
fetchedResultsController.postFetchComparator= ^(id a, id b) {
Venue* v1 = (Venue*)a;
Venue* v2 = (Venue*)b;
double d1 = [v1.coreLocation distanceFromLocation:sourceLocation];
double d2 = [v2.coreLocation distanceFromLocation:sourceLocation];
return [@(d1) compare:@(d2)];
};
NSError *error = nil;
if (![fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
由于它是一个旧项目,它没有 ARC,因此当您包含这两个文件时,请记住在目标、构建阶段中使用编译器标志 -fno-objc-arc 标记 .m。另请注意,开发人员认为代码尚未准备好生产,因此如果使用它,请务必进行充分的测试。
在我上面的代码中,我的 Venue 托管对象子类上有一个瞬态属性 coreLocation,您可以在此处查看如何实现它。此外,距离计算效率低下,您可能希望将距离缓存在对象中,而不是在每次比较时重新计算它。
最后,这个项目似乎是因为创建者 Daniel Thorpe 的 Stackoverflow 问题没有得到解答,导致他自己解决了问题并发布了唯一的答案,所以我认为如果你觉得他的项目有用,你可以给他的帖子投票就像我一样。