2012-04-20 55 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來解決此問題。