3

我有一個UITableView,顯示名爲「Documents」的大量實體的子集。該子集由另一個實體「選擇」定義。選擇被命名,有序的文件列表。如何以編程方式切換UITableView的NSFetchedResultsController(或其謂詞)?

它工作正常,除非我想在運行時更改顯示的選擇。我只得到一個空白列表。

基本上,我需要改變我的NSFetchedResultsController持有的謂詞,以便新的謂詞使用另一個Selection。我無法讓它工作。我最後一次嘗試就是要完全擺脫NSFetchedResultsController的並對其重新分配:

- (void) displaySelection:(Selection *)aSet 
{ 
self.currentSelection = aSet; 
self.fetchedResultsController = nil; 
// methods here don't all use the property but directly the ivar, so we must trigger the getter 
[self fetchedResultsController]; 
[self.tableView reloadData]; 
} 

當然,在NSFetchedResultsController吸氣做正確的事:

- (NSFetchedResultsController *)fetchedResultsController 
{ 
    if (fetchedResultsController != nil) { return fetchedResultsController; } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext]; 
    [fetchRequest setEntity:entity]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier]; 
    [fetchRequest setPredicate:predicate]; 
<snip> 
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 
<snip> 
    return fetchedResultsController; 
} 

此代碼工作的第一次,因爲初始選擇已設置。但是,調用displaySelection:時,tableview變爲空白。

一個非常類似的問題被問在NSFetchedResultsController fetch request - updating predicate and UITableView

而答案是擺脫NSFetchedResultsController的。我不想這樣做,因爲NSFetchedResultsController在這裏帶來了很多有用的好東西(例如緩存,部分加載......)。問題仍然存在:如何在由NSFetchedResultsController支持的UITableView中「切換」數據,其中「switch」意味着具有不同的謂詞,或者甚至(不在我的情況下)具有不同的實體。

爲了完整起見,請注意,由於從Selection到Document的多對多關係是有序的,所以它通過一個稱爲DocInSelection的中間輕量級實體進行處理,該實體具有「排序」屬性和兩個很多對文檔和選擇的一對一關係。

感謝您的任何建議。

回答

6

當我發佈我的問題後,我嘗試了其他問題的OP顯示的代碼的變體。這個對我有用。它是:

- (void) displaySelection:(Selection *)aSet 
{ 
    if (aSet != self.currentSelection) { 
     self.currentSelection = aSet; 

     NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest]; 
     NSPredicate *predicate = nil; 
     NSEntityDescription *entity = nil; 
     entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext]; 
     predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier]; 
     [fetchRequest setEntity:entity]; 
     [fetchRequest setPredicate:predicate]; 

     [NSFetchedResultsController deleteCacheWithName:@"Root"]; 

     NSError *error = nil; 
     if (![[self fetchedResultsController] performFetch:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     }  
    } 
    [self.tableView reloadData]; 
} 
+1

如果你打算deleteCacheWithName:@「Root」每一次,爲什麼甚至創建緩存。如果不使用緩存,則傳入緩存名稱爲nil。儘管緩存是首先使用NSFRC的好處之一。 – bandejapaisa 2011-08-15 13:05:26

+0

我想,雖然當前選擇(可能很大)保持不變,但緩存由「NSFetchedResultController」使用,效果良好。 「每一次」可能都不是那麼經常。 Apple還在[修改提取請求]中說過(http://developer.apple.com/library/iOS/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html)「如果您正在使用緩存,請將其刪除(使用deleteCacheWithName :)。「蘋果還增加了「通常情況下,如果您要更改獲取請求,則不應該使用緩存」。測試應該有助於決定緩存是否有益於此。 – 2011-08-18 08:17:28

15

由於NSFetchedResultsController(FRC)是一個對象,因此可以像存儲其他對象一樣存儲它的實例。

一種有用的技術是在字典中初始化和存儲多個FRC,然後將tableview控制器的fetchedResultController屬性設置爲您目前需要的FRC。這對於諸如使用分段控件對同一表中的不同屬性或實體進行排序等情況很有用。這種技術的優點是可以保持單獨的FRC緩存,從而可以顯着加快讀取速度。

只需確保在交換控制器之前發送tableview本身beginUpdates,然後在完成之後發送endUpdates。當FRC被換出時,這可以防止表格在窄窗口中詢問數據。然後致電reloadData

+0

啊啊!有趣。由於這組選擇取決於用戶的操作,所以對我來說這可能不太合適。但我會記住。謝謝。 – 2010-08-16 16:14:10

+1

你將如何做UICollectionView的beginUpdate/endUpdates,因爲它沒有相應的方法? – Gujamin 2013-07-30 18:51:28

3

雖然這可能工作有iOS的參考圖書館在一張紙條,困擾我:

重要:不得修改 獲取請求。例如,您必須 不會更改其謂詞或排序 排序。

來源:NSFetchedResultsController Class Reference

此附加說明不了iOS 3.2參考庫中不存在。

只是想指出這一點。

+1

我沒注意到那個音符。如果我們能從蘋果那裏得到解釋,那將是最好的。我有點理解它:由於FetchedResultController保持其獲取結果,從它的腳下拉動它的fetchRequest地毯可能導致不一致。這就是爲什麼上面的代碼片段1-清除緩存,2-再次執行提取請求,3-請求tableView重新加載其數據。現在看起來不錯,但我想就此發表一些官方言論。 – 2010-09-16 14:03:56

0

一個重要的注意事項:如果您「覆蓋」了一個fetchController對象,請確保您先清除它的.delegate,否則在刪除行時會發生崩潰,例如舊的fetchController及其委託獲取事件。

相關問題