7

使用核心數據對多關係時存在一個長期存在的問題,即很難根據Parent實體上的NSSortDescriptor對實體進行排序children的數量與Child實體處於一對多關係。這與NSFetchedResultsController結合使用時尤其有用。通常,初始化排序描述爲:NSSortDescriptor根據核心數據對多關係中的項目數排序

NSSortDescriptor *sortByNumberOfChildren = [[NSSortDescriptor alloc] initWithKey:@"[email protected]" ascending:NO]; 

導致異常'Keypath containing KVC aggregate where there shouldn't be one; failed to handle [email protected]

的iOS 6.1,我加入了國際志願者組織訪問-countOf<Key>作爲屬性我的管理對象模型作爲一個整數發現了一個修復類型。我沒有在我的NSManagedObject子類中爲這個屬性實現任何東西,因爲所有的魔法似乎都在發生。 (見https://stackoverflow.com/a/15546371/2042527)。

但是,這不適用於iOS 6.0。在這裏,我發現,添加下面的方法你NSManagedObject子解決問題:

- (NSUInteger)countOfChildren{ 
     return [self.children count]; 
    } 

將兩個不兩個SDK的解決這個問題。相反,它打破瞭解決方案。

有沒有人知道爲什麼會發生這種情況,以及爲什麼兩者之間存在差異,儘管在iOS 6.0和iOS 6.1之間沒有提及Core Data或Foundation的更改。

+0

您是否將此添加到'NSManagedObjectModel'?很難看到甚至可以編譯,更不用說工作了。 NSManagedObjectModel與其他類沒有任何關係。 – 2013-03-21 16:16:44

+0

對不起,我的壞,我的意思是'NSManagedObject'子類也是第二次。我糾正了錯誤。 – 2013-03-21 16:44:49

+0

不是解決您的具體問題,而是另一種觀點:取孩子和計算不同父母的數量如何?也許這[post](http://stackoverflow.com/questions/9157436/distinct-count-via-core-data-nsexpression-into-nsfetchedresultscontroller)可以幫助你。 – Paul 2013-07-09 12:13:06

回答

6

我認爲通過說「包含KVC聚合的Keypath不應該有一個;未能處理兒童。@ count」Core Data希望告訴您它不支持這種排序描述符。這很可能是因爲當後臺SQLite存儲接收到您的提取請求時,它必須生成SQL來執行提取請求所描述的內容。 「兒童。@伯爵」的情​​況實際上比人們想象的更爲複雜。

重寫-countOfChildren的「修復」並不是一個真正的修復。讓我們假設這一問題解決了問題,然後在每個Parent上調用-countOfChilden。當你第一次訪問self.children時,Core Data需要執行一個SQL查詢來確定(至少)子進程的主鍵,創建NSManagedObjectIDs,NSManagedObjects並返回結果。如果這個工作,那麼你會看到非常糟糕的表現。

有幾種解決方案可以解決您的問題。

1.商店孩子在持久屬性計數

只需添加屬性(名稱:cachedCountOfChildren,類型:整數64位)到父實體。在您的控制器層(不在您的模型層中),每次將子對象分配給父對象時,都會將cachedCountOfChildren遞增1,並且每次從父對象中移除一個子對象時遞減cachedCountOfChildren。然後在排序描述符鍵中使用cachedCountOfChildren。這將會有很好的表現。

2.使用字典搜索結果

設置你的NSFetchRequest到NSDictionaryResultType的與resultType。這將導致-executeFetchRequest:error:返回NSDictionaries而不是NSManagedObjects。帶有NSDictionaryResultType的NSFetchRequest可以做不同的事情。例如,你可以使用setPropertiesToGroupBy和NSExpression(...)。請參閱WWDC會議「使用帶有Core Data的iCloud(2012)」(從幻燈片122開始)以供參考。基本上他們告訴你如何構建將返回其中包含具有這種結構的字典數組的請求:

(
{ 
    countOfChildren = 1; 
    parentName = "hello"; 
}, 
{ 
    countOfChildren = 134; 
    parentName = "dsdsd"; 
}, 
{ 
    countOfChildren = 2; 
    parentName = "sdd"; 
} 
) 

正如你看到的,你會得到一個未排序的結果返回。但是通過countOfChildren對這個數組進行排序可以非常有效地在內存中完成。 Core Data生成的SQL在這種情況下也會非常高效,您將能夠精確指定字典應包含的屬性。所以結果也應該是非常有效的。這個解決方案的優點是你不必跟蹤countOfChildren。

根據您的情況,您必須決定哪種解決方案最適合您自己。

+0

爲什麼不在NSManagedObject的子類(即模型層)上實現? – 2013-10-07 13:29:14

+0

執行什麼? 1或2? – 2013-10-08 12:41:02

+0

我想知道爲什麼你爲1寫了以下內容:'在你的控制器層(不在你的模型層),每次你將cachedCountOfChildren增加1 ...'。 – 2013-10-08 12:48:05