使用NSFetchedResultController进行自定义排序(子类化NSSortDescriptor)

我想提供使用NSFetchedResultsController和NSSortDescriptor的自定义排序。

当通过NSSortDescriptor消息自定义排序 - (id)initWithKey:ascending:selector:是不可能的(参见这里)时,我尝试使用NSSortDescriptor派生类来覆盖compareObject:toObject:消息。

我的问题是,compareObject:toObject:并不总是被调用。 它似乎只在数据已经在内存中时才被调用。 当数据是第一次从商店检索时,有一种使用基于数据库的排序而不是compareObject:toObject的优化。 (看这里)。

我的问题是:如何强制NSFetchedResultscontroller使用compareObject:toObject:消息来排序数据? (并且可以处理大数据集)

一种解决方案是使用二进制存储而不是sqlite存储,但我不想这样做。

另一个解决方案是
-call performFetch通过SQL对数据进行排序(不调用compareObject)
- 对数据进行修改并将其反转。
再次调用performFetch(调用compareObject)
它在我的情况下工作,但它是一个黑客,我不知道它会一直工作(尤其是大数据集(大于批量大小))。

更新:您可以使用CoreDataBooks示例重现。
在RootViewController.m中,添加这个丑陋的黑客:

- (void)viewWillAppear:(BOOL)animated {
    Book* book = (Book *)[NSEntityDescription insertNewObjectForEntityForName:@"Book" 
                 inManagedObjectContext:[self fetchedResultsController].managedObjectContext];
    [[self fetchedResultsController] performFetch:nil];
    [[self fetchedResultsController].managedObjectContext deleteObject:book];
    [self.tableView reloadData];
}

在RootViewController.m中,将排序描述符代码替换为:

MySortDescriptor *myDescriptor = [[MySortDescriptor alloc] init];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:myDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];  

添加MySortDescriptor类:

@implementation MySortDescriptor

-(id)init
{
    if (self = [super initWithKey:@"title" ascending:YES selector:@selector(compare:)])
    {

    }
    return self;
}

- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2
{
    //set a breakpoint here
    return [[object1 valueForKey:@"author" ] localizedCaseInsensitiveCompare:[object2 valueForKey:@"author" ] ];
}

//various overrides inspired by [this blog post][3]
- (id)copy
{
    return [self copyWithZone:nil ];
}
- (id)mutableCopy
{
    return [self copyWithZone:nil ];
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
    return [self copyWithZone:zone ];
}
- (id)copyWithZone:(NSZone*)zone
{
    return [[MySortDescriptor alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]];
}
- (id)reversedSortDescriptor
{
    return [[[MySortDescriptor alloc] initWithKey:[self key] ascending:![self ascending] selector:[self selector]] autorelease];
}
@end

关于你的问题和评论。 您将需要将对象拉入内存中对其进行排序。 一旦他们在内存中,你可以使用一种方便的方法来确定一个点的距离。

要减少您拉入内存的对象的数量,您可以计算最大值和最小值,然后对这些值进行过滤,从而在排序之前减小搜索半径。

除非计算值在内存中,否则无法对计算值进行排序。

链接地址: http://www.djcxy.com/p/36125.html

上一篇: Custom sorting with NSFetchedResultController (subclassing NSSortDescriptor)

下一篇: Using time based transient property with NSFetchedResultsController