5

我正在尝试使用 NSSortdescriptor 使用指向 NSDate 值的键对我的 NSFetchRequest 结果进行排序。我的获取结果完全随机出现,没有明确的原因。

我正在使用的 NSManagedObjectContext 更新为在 NSOperation 的子类上创建的嵌套子上下文中的保存。我知道这一切都已成功完成,因为我可以从父(主)上下文中获取所需的所有数据。从中获取只是不会按日期排序!

奇怪的是;用于在两个日期之间选择实体(称为“Tweet”)的谓词工作得很好!

这是一些代码来说明我的问题:

NSSortDescriptor* timeDescriptor = [NSSortDescriptor
                                        sortDescriptorWithKey:@"time"
                                        ascending:NO
                                        selector:@selector(compare:)];

NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"Tweet"];
[request setSortDescriptors:[NSArray arrayWithObjects:timeDescriptor, nil]];

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"((time >= %@) AND (time <= %@))",startDate,endDate];
[request setPredicate:predicate];

NSManagedObjectContext* context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:[[NSApp delegate] managedObjectContext]];
[context performBlock:^{
    NSError* error = nil;
    NSArray* results = nil;

    results = [context executeFetchRequest:request error:&error];
    // Results here are not ordered correctly

    // 2nd try sorting results using fetched array (works!)
    results = [results sortedArrayUsingDescriptors:[NSArray arrayWithObjects:timeDescriptor, nil]];

    // This works too but not needed anymore
    /*results = [results sortedArrayUsingComparator:^(id obj1, id obj2) {
        Tweet* tweet1 = (Tweet*)obj1;
        Tweet* tweet2 = (Tweet*)obj2;
        //return [tweet1.time compare:tweet2.time]; // ascending
        return [tweet2.time compare:tweet1.time]; // descending
    }];*/

    if ([results count] > 0) {
        for (uint i = 0; i < [results count]; i++) {
            Tweet* tweet = [results objectAtIndex:i];
            NSDate* date = Tweet.time;
            NSLog(@"tweet date: %@", date);
        }
    }
}];

谁能告诉我为什么 NSSortDescriptor 对我的提取不起作用?

谢谢!

- 更新 -

当我从主线程上的主(父) managedObjectContext 获取而不使用 performBlock 方法时,NSSortDescriptor 似乎工作正常。这仍然不能帮助我对 NSPrivateQueueConcurrencyType managedObjectContext 进行排序提取。在 performBlock 中创建 NSFetchRequest、NSSortDescriptor 和 NSPredicate 也不能解决问题。

4

3 回答 3

5

我也遇到了问题。我发现除非数据一直保存回持久存储,否则如果主上下文中的数据是脏的,即被修改,排序将不起作用。

例如,如果上下文是干净的,没有挂起的更改,则排序工作。如果我只更改父上下文中实体的一个属性,则私有队列子上下文中的排序不起作用。这是非常不幸的。我现在也使用数组方法进行排序,但它没有在 NSFetchRequest 中排序那么快,特别是因为我的数据已经被该键索引了。在 fetch 请求中对其进行排序会快得多。

我的猜测是,由于上下文中存在未保存的更改,并且 NSFetchRequest 转到 SQLite 数据库本身,其中更改尚不存在(未保存上下文),因此它根本无法在数据库级别进行排序。

但总的来说,它非常令人困惑,闻起来像个虫子。

于 2012-05-14T08:01:47.647 回答
3

我有完全相同的问题。我通过将 NSFetchRequest 实例中的 includesPendingChanges 属性设置为 NO 解决了这个问题。

于 2012-05-28T23:50:11.073 回答
-1

当使用默认的 compare: 选择器时,您可以简化描述符:

NSSortDescriptor* timeDescriptor = [NSSortDescriptor
                                        sortDescriptorWithKey:@"time"
                                        ascending:NO];

但这是一个问题。我认为关键是您正在从嵌套的子上下文进行更新。验证您的对象是否具有永久对象 ID;他们可能还没有收到它们,因此这可能是您获取的问题。如果是,则在保存嵌套子上下文之前尝试调用 objectPermanentIDsForObjects:。

于 2012-04-22T08:11:34.967 回答