2014-01-05 60 views
1

好的,我越來越多地瞭解這個問題,因爲我注意到由於這個原因我的應用程序出現了一些滯後現象。我注意到重新排序的問題,但它也發生在其他地方。我有一個CoreDataViewController類,所有我的表視圖控制器的子類。在這個類中,我基本上擁有所有NSFetchedResultsController委託方法,就像它們在Apple文檔中一樣。NSFetchedResultsControllers在不同的視圖控制器互相更新?

然後我試圖找出變化是如何經常被這個NSFetchedResultsController注意到,找出我的時間滯後:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    if(self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return; 
    NSLog(@"ControllerDidChangeContent"); 
    TICK; 
    [self.tableView endUpdates]; 
    TOCK; 
} 

因此,例如,在我的視圖控制器A,我有這樣的讀取請求(從viewDidLoad中調用):

- (void)setupFetchedResultsController 
{ 
    //NSError *error = nil; 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SpendingCategory"]; 
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]]; 
    //[self.mainCategory.managedObjectContext executeFetchRequest:request error:&error]; 
    request.predicate = [NSPredicate predicateWithFormat:@"belongsToMainCategory = %@", self.mainCategory]; 

    self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request 
                     managedObjectContext:self.mainCategory.managedObjectContext 
                     sectionNameKeyPath:nil 
                        cacheName:nil]; 
} 

如果我在這個視圖控制器更改屬性爲我的目標,我的日誌打印出只有一次的評論「ControllerDidChangeContent」,因爲它應該。速度和預期一樣快。我的意思是真的只是一個簡單的屬性改變,只是改變了一些號碼或串等,如:

spendingCategory.name = @"Hello world"; 

然而,如果我已經訪問其設置的NSFetchedResultsController以及在viewDidLoad中另一個視圖控制器,我的日誌打印出來兩次。這裏是第二個NSFetchedResultsController:

- (void)setupFetchedResultsController 
{ 
    self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext; 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SpendingCategory"]; 

    NSSortDescriptor *mainCatPosition = [[NSSortDescriptor alloc] 
          initWithKey:@"belongsToMainCategory.position" ascending:YES]; 
    NSSortDescriptor *spendingCatPosition = [[NSSortDescriptor alloc] 
          initWithKey:@"position" ascending:YES]; 

    request.sortDescriptors = [NSArray arrayWithObjects:mainCatPosition,spendingCatPosition,nil]; 
    request.predicate = [NSPredicate predicateWithFormat:@"liveBudget = %@", [NSNumber numberWithBool:YES]]; 

    self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request 
                     managedObjectContext:self.managedObjectContext 
                     sectionNameKeyPath:@"belongsToMainCategory.position" 
                        cacheName:@"LiveBudget"]; 

} 

我之前提到的簡單的屬性改變需要更長的時間。這是因爲現在我的日誌打印出兩次(!)ControllerDidChangeContent。第一個TICK-TOCK仍然像以前一樣快,但第二個則需要一秒以上。我想這是因爲我有兩個NSFetchedResultsController看着同一個實體。

  1. 問題: 我還不太明白他們爲什麼互相影響?我的意思是我確定我更新了一個視圖控制器中的屬性,所以另一個當然應該注意到這個改變,但爲什麼兩個didChangeContent被觸發?

  2. 問題: 我該如何避免這種情況?或者我該如何改進?

+0

每個VC收到一個回調?或者一個接收重複的回調?表格視圖單元格包含什麼內容?你在哪裏設置代表? – Wain

+0

每個VC在其視圖加載完成後都設置了FRC後會收到兩個回調。表視圖單元格包含所有屬性(3個NSNumbers,2個字符串)。並且代表被設置在視圖中也加載了 – MichiZH

回答

0

我認爲最好是檢查爲什麼在轉向此解決方案之前1秒停止。
我自己,我沒有經歷過在同一個環境下使用多個FRC時的延遲,所以我的猜測是問題在於別處。

爲您的問題:

  1. 的FRC正在監聽「NSManagedObjectContextObjectsDid 變化通知」,讓所有的FRC對同一對象相同的上下文聽會引發他們的代表的方法時,這些對象被改變。因此,很明顯爲什麼你的日誌打印了兩次(2個不同的FRC改變了他們的內容)

  2. 1 [sec]是阻塞主線程的一段時間,應該解決(應該檢查什麼可以完成) 。正如我所提到的,當在相同的上下文中使用FRC時,無法避免這種情況,但是您可以爲每個創建的VC創建一個子上下文,使FRC僅監聽該子上下文,然後更改將僅對其他人可見FRC在節省上下文鏈時。只要你的VC堆棧不是很深,這應該不是一個真正的問題。無論如何,你希望你的其他風險投資者在更新桌面視圖時得到更新,以便提供順暢的用戶體驗,所以如果更新花費太長時間,你應該明白爲什麼。

+0

謝謝您的評論。如果我創建了一個子上下文並保存它,那麼即使該提取未被再次執行,我的其他上下文也會看到這些更改?所以我可以在VC 1中創建一個子上下文1改變一切,保存上下文並且VC 2立即顯示更改?再次檢查之後,這個問題主要出現在重新排序中,我自己更改屬性並停止FRC檢查更改,直到完成。改變一切後,我保存上下文並讓他再聽一遍。 ([fetchedResult setValue:[NSNumber numberWithInt:i ++] forKey:@「position」];) – MichiZH

+0

更改排序大概會更改多個對象,而不僅僅是一個... – Wain

+0

@MichiZH保存子上下文將更改傳播給父代上下文,這又轉化爲父上下文中的變化,並且監聽父上下文的FRC不需要重新獲取對象(執行提取)。如果您的設置是VC1(父級) - > VC2(子級),並且您在子級中進行了更改,則當您保存子級上下文時,父級上下文將獲取更改並更新VC1。更改FRC委託方法內的對象是有問題的,因爲更改將在下一個runloop中再次調用這些方法。 –

相關問題