2012-04-20 58 views
4

我想使用NSSortdescriptor使用指向NSDate值的键对NSFetchRequest结果进行排序。我的提取结果完全是随机的,没有明确的理由。NSSortdescriptor对从NSManagedContext获取结果无效

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

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

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

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不是为我取的工作?

谢谢!

- 更新 -

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

回答

-1

当使用默认的比较:选择器,可以简化描述:

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

但是,这是题外话。我认为关键是你要从嵌套的子上下文更新。验证你的对象是否有永久的对象标识符;他们可能还没有收到他们,因此这可能是你的提取问题。如果是,则在保存嵌套的子上下文之前尝试调用objectPermanentIDsForObjects:。

4

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

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

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

但总的来说,这是非常混乱和气味像一个错误。

3

我有完全相同的问题。我已经通过将NSFetchRequest实例中的includesPendingChanges属性设置为NO来解决此问题。