2009-11-21 47 views
2

我在我的Thing實體上有一個謂詞結果控制器,它看起來像這樣:「thingDomain.domainCurrentAccount!= NULL」。它找到了當前域中的所有Thing對象。當前域由帳戶實體和其中一個域實體之間的一對一關係定義。每件事都屬於一個域,每個域都有很多東西。除一個域外,所有域都與該帳戶具有NULL關係。是否重新獲取NSFetchedResultsController執行任何操作?

這個作品和我的tableview很開心。

後來我通過修改與Account的關係來更改當前域。我將更多的東西添加到現在是當前域的域中,因爲它們滿足謂詞,所以它們被添加到tableview中。但屬於現在非當前域的東西仍然保留在tableview中,即使它們不再滿足謂詞。

我試過重新抓取,但沒有任何效果,所以我對再次抓取的內容感到困惑。它是否重新評估針對實體的謂詞?

我通過在更改當前域之前刪除當前域中的所有內容來解決了這個問題,但覺得我不應該這樣做。

回答

4

您是否在重新執行提取操作後重新加載表格視圖?

這爲我工作:

self.fetchedResultsController = nil; 
NSError *error = nil; 
if (![self.fetchedResultsController performFetch:&error]) { 
    NSLog(@"Error in refetch: %@",[error localizedDescription]); 
    abort(); 
} 

[self.tableView reloadData]; 

UPDATE
獲取的成果控制器觀察事物對象的變化,而不是域對象。由於我們正在更改域對象上的帳戶,因此獲取的結果控制器不會更新(新的Thing除外)。
理想的解決方案是告訴託管對象上下文或獲取結果控制器哪些確切的事情已經「改變」(先前擁有該賬戶的域中的事物上的循環)的方式,但這仍然是手動過程。
另一種方法是再次執行提取並重新載入適用於我的表格。

我創建根據您的描述這個模型:

帳戶< --->域名< --- >>東西

爲了測試這一點,我創造的事「一」和「二」中域domainOne和事物「三」,「四」和「五」域域二。 domainOne擁有賬戶,而domainTwo沒有賬戶。
當應用程序加載時,表視圖按預期顯示事物「一」和「兩」。
當我點擊「更改」時,domainTwo被分配帳戶,並且domainOne丟失其帳戶。此外,在domainTwo中創建了一個名爲「Six」的新事物。
即使他們不再符合謂詞,「Six」與「One」和「Two」一起出現。這與您描述的問題相符。
然後,我點擊「Refetch」,表格會重新加載「Three」,「Four」,「Five」和「Six」。這是所需的行爲。

下面是相關的視圖控制器代碼:

- (void)addTestData { 
    account = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:self.managedObjectContext]; 
    domainOne = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext]; 
    domainTwo = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext]; 
    [domainOne setValue:account forKey:@"domainCurrentAccount"]; 

    NSArray *thingNames = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", nil]; 
    for (NSString *name in thingNames) { 
     NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext]; 
     [thing setValue:name forKey:@"thingName"]; 
     if (name == @"One" || name == @"Two") { 
      [thing setValue:domainOne forKey:@"thingDomain"]; 
     } else { 
      [thing setValue:domainTwo forKey:@"thingDomain"]; 
     } 
    } 
} 

- (void)change { 
    [domainTwo setValue:account forKey:@"domainCurrentAccount"]; 
    [domainOne setValue:nil forKey:@"domainCurrentAccount"]; 
    NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext]; 
    [thing setValue:@"Six" forKey:@"thingName"]; 
    [thing setValue:domainTwo forKey:@"thingDomain"]; 
} 

- (void)refetch { 
    self.fetchedResultsController = nil; 
    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) { 
     NSLog(@"Error in refetch: %@",[error localizedDescription]); 
     abort(); 
    } 

    [self.tableView reloadData]; 
} 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UIBarButtonItem *changeButton = [[UIBarButtonItem alloc] initWithTitle:@"Change" style:UIBarButtonItemStyleBordered target:self action:@selector(change)]; 
    self.navigationItem.leftBarButtonItem = changeButton; 
    [changeButton release]; 

    UIBarButtonItem *refetchButton = [[UIBarButtonItem alloc] initWithTitle:@"Refetch" style:UIBarButtonItemStyleBordered target:self action:@selector(refetch)]; 
    self.navigationItem.rightBarButtonItem = refetchButton; 
    [refetchButton release]; 

    [self addTestData]; 

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

我試過,沒有效果。不管怎麼樣,因爲獲取的結果控制器正在關注MOC上的所有更改,並且所有其他表都更新了它需要的集合,所以它不應該是必需的。重新加載桌面視圖是最後的手段,因爲它不是動畫並殺死任何正在進行的動畫。 – 2009-11-21 15:42:09

+0

我解釋了爲什麼這不是我們最初預期的方式,並增加了我的原始解決方案的細節。 – gerry3 2009-11-21 20:08:42

+0

有趣,但是你的代碼有一個關鍵的區別:在重新讀取你扔掉當前提取的結果控制器並創建一個新的。我具體詢問使用相同的控制器並要求它執行另一次獲取,因此,我假設,使其重新評估所有實體與謂詞。 這可能是什麼都不做,但文檔沒有說。提取可能是一次性事件,一旦有結果,不會再提取。沒有「取消」來拋棄它所具有的結果。 – 2009-11-21 20:37:54

相關問題