2014-12-06 84 views
6

我運行程序創建使用NSTreeControllerNSOutlineView中顯示的核心數據內容。第二次運行我的程序時,我想清理我的NSTreeController的內容,並運行下面粘貼的方法。該方法掛起很長一段時間(600秒)才能完成或崩潰。如果我的NStreeController中有幾個實體(500-1000),那麼與通過此方法的許多(200,000個)實體通過該方法相比,它花費的時間要少得多,如果它通過的話。我需要知道的是,如果在重新運行我的程序並再次填入NStreeController之前,有更好的方法來清除/刷新/重置我的NStreeController的內容以清除我的NSoutlineView。具體而言,我希望我的NSOutlineView對我的NSTreeController的內容的更改做出快速響應,並且我需要將我的核心數據驅動的內容NSTreeController重置。重置核心數據驅動的樹控制器內容

-(void) cleanSDRDFileObjects 
{ 
    __weak __typeof__(self) weakSelf = self; 
    dispatch_async(dispatch_get_main_queue(), ^{  
     [weakSelf.outlineView collapseItem:nil collapseChildren:YES]; 
     [weakSelf.coreDataController._coreDataHelper.context performBlockAndWait:^{ 

      NSEntityDescription *entityDescription = [NSEntityDescription 
                entityForName:@"SDRDFileObject"          inManagedObjectContext:weakSelf.coreDataController._coreDataHelper.context]; 

      NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
      [request setEntity:entityDescription]; 

      NSArray * result = [weakSelf.coreDataController._coreDataHelper.context executeFetchRequest:request error:nil]; 
      for (id fileobject in result){ 
       [weakSelf.coreDataController._coreDataHelper.context deleteObject:fileobject]; 
      } 
      [weakSelf.coreDataController._coreDataHelper.context processPendingChanges]; 

      NSLog(@"Finished deleting all objects"); 
     }]; 
    }); 
} 

的managedobjectcontext(context)運行爲NSMainQueueConcurrencyType類型,並且該方法在主線程上運行。有關改進的建議或有關重置/刷新NSOutlineView +核心數據組合的有用示例將不勝感激。謝謝。歡呼聲,特隆

作爲對@TomHarringtons問題的迴應,我拍了一張我的Time Profiler的照片。我真的不會再繼續。

enter image description here

當我重新運行應用程序,與processPendingChanges註釋掉其仍掛。

enter image description here

更新

我相信我解決了這個,但我,爲什麼這個工作稍微不確定的。看來我的第一種方法進入了一個無限循環,沒有釋放它的對象。下面這個簡單的解決方案工作:

 __weak __typeof__(self) weakSelf = self; 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     [weakSelf.coreDataController._coreDataHelper.context reset]; 
     }); 

我敢肯定,正確地清空一個管理對象方面,我將不得不單獨刪除每一個實體。重置功能似乎非常暴力,它實際上是否清理內存並確保一切正常?如果有人想闡明這一點,將不勝感激。

+0

將/ didChangeValueForKey通常從'self'實例的存取調用。你爲什麼要用這種方法叫他們?而NSTreeController甚至沒有keyPath「children」。它有一個keyPath「childrenKeyPath」。無論如何 - 你在尋找'rearrangeObjects'? – stevesliva 2014-12-06 05:55:05

+0

['rearrangeObjects'](http://stackoverflow.com/questions/23773827/how-can-i-determine-if-apple-methods-are-asynchronous/)有時會調度GUI刷新在主線程隊列,所以它可能與你的問題有關。儘管如此,你使用KVC方法是令人恐懼的,你應該在使用will/didChangeValueForKey之前研究它。我也想知道,當你將背景上下文中的變化推送到mainThread/GUI上下文時。 – stevesliva 2014-12-06 05:59:10

+0

@ stevesliva感謝您的意見。我意識到當我隨機測試KVO(病態學習)時,我複製並粘貼了我的代碼。我一直在使用KVO佈置物體(沒有成功)。我現在看到我的outlineView委託崩潰,因爲我刪除的實體,特別是當我刪除其孩子之前刪除實體和outlineview嘗試更新解除分配的項目。如果您對重置由Core Data驅動的tableview或outlineview的最佳實踐有很好的建議。我已經搜索了這個問題,但沒有找到關於如何重置核心數據驅動視圖的好例子。 – 2014-12-07 00:09:36

回答

1

再看一遍,您在performBlockAndWait中獲取了一個類型的所有對象 - 這會阻止主線程,因爲您擁有mainQueueConcurrency並且使用了performBlock的andWait版本。

然後您逐個刪除每個對象。這些對象位於帶有大綱視圖的樹形數據結構中(請參閱堆棧跟蹤中的KVO消息)。這些對象具有需要由核心數據維護的多對多關係,地獄,你甚至可以有級聯刪除規則。 (請參閱堆棧跟蹤中的propagateDelete和maintainInverseRelationship)無論如何,您開始請求數據源和視圖在主線程上開始執行大量工作。如果您想迭代背景中的所有對象,可以嘗試使用帶有privateQueueConcurrency的子MOC。

但是,像指示的評論:

的NSManagedObjectContext的reset最肯定的釋放內存,它的罰款你想在這裏做什麼:打擊一切離開。

它迴避了爲什麼你從商店加載模型上盤擺在首位,雖然這個問題。

如果您需要核心數據,但不是運行程序的時間間隔內的持久性,可以使用NSInMemoryStoreType存儲來初始化persistentStoreCoordinator,而不是將其指向文件URL。

+0

我不知道該NSInMemoryStoreType,我也只用核心數據爲「內存」(非持久性),所以這是一個偉大的小費!謝謝! – 2015-02-19 23:53:16

+0

我最近聽說它建議用於測試目的......你可以編寫單元測試,創建內存中的商店並扔掉它們,而不需要在你的測試遊樂場提供磁盤位置。但在這種情況下,它在功能上也符合該法案。 – stevesliva 2015-02-20 01:32:24