2013-05-08 32 views
2

假設Recipe對象具有一個或多個IngredientNSSet,並且在覈心數據中建模了相同的關係。訪問在覈心數據中建模的類的屬性的正確方式

鑑於recipe,訪問其成分的正確方法是什麼?

在這個例子中,使用recipe.ingredients似乎很自然,但我可以同樣使用NSFetchRequestIngredient實體,NSPredicate通過配方匹配。

現在讓我們說我只想要「收集」的成分。這對我來說不太清楚 - 我是否應該使用配方的提取請求,而配料的限制條件和收集狀態?或通過recipe.ingredients循環?

在秤的另一端,也許我只需要這個配方的成分,也出現在其他食譜。現在,獲取請求似乎更具吸引力。

什麼是正確的一般方法?或者這是一個個案情況?我感興趣的影響:

  1. Consitancy
  2. 可讀性
  3. 性能
  4. 魯棒性(例如,很容易做出錯誤的讀取請求編譯器不能趕上)。

回答

0

在這個例子中,使用recipe.ingredients似乎很自然,但我可以同樣使用NSFetchRequest for Ingredient實體和 NSPredicate通過配方匹配。

爲什麼你會怎麼做時,你可以做到前者,後者?你已經有了配方,它已經有一套配料,所以沒有必要查看全部的配料,並過濾掉那些與已有配方相關的配料。

現在讓我們說,我只想要'收集'的成分。這 是不太清楚,我 - 我應該使用配方和收集到的狀態的成分 與謂詞限制爲獲取請求?或通過recipe.ingredients循環 ?

應用謂詞到配方的成分:

NSPredicate *isCollected = [NSPredicate predicateWithFormat:@"collected == YES"]; 
NSSet *collectedIngredients = [recipe.ingredients filteredSetUsingPredicate:isCollected]; 

在天平的另一端,也許我需要從 這個食譜,也出現在其他配方只成份。現在,獲取請求 似乎更具吸引力。

同樣,這裏使用提取請求似乎浪費,因爲你已經可以很方便地設定成分,可能是最終的結果,這是潛在的一組比一組的所有成分的小得多。使用與上述相同的方法,但更改謂詞以測試與每種成分相關的配方。喜歡的東西:

NSPredicate *p = [NSPredicate predicateWithFormat:@"recipes > 1"]; 
NSSet *i = [recipe.ingredients filteredSetUsingPredicate:p]; 

什麼是正確的一般方法?

提取請求是搜索給定實體的所有實例的好方法。你總是要開始與獲取請求獲取一些對象的工作。但是,當你想要的對象與某個已有的對象有某種關係時,你可以(也應該)使用這些關係來獲得你想要的。

+0

如果您沒有使用預取,使用謂詞「內存中」過濾器的關係會逐個對對象進行排序,所以對於100件商品的關係,您將有100次訪問該商店,並且性能非常差。您必須定義預取關係以避免這種情況。 – 2013-05-08 22:00:26

+0

@DanShelly謝謝你指出! – Caleb 2013-05-08 22:55:26

1

讓我們按順序經過這些。

  1. 獲取成分特定Recipe,當你已經有一個參考:每次使用recipe.ingredients

  2. 獲取爲具有特定值(例如布爾標誌值)的特定Recipe成分:最簡單的可能是如上述開始與recipe.ingredients然後使用類似NSSetobjectsPassingTest來過濾他們。最優雅的是在Recipe上設置一個提取的屬性,它只是返回這些成分而沒有額外的代碼(語法可能不會立即明顯,詳情請參閱a previous answer I wrote)。這兩個可能表現平平。最不吸引人的是取回請求。

  3. 出現在多個配方實例獲取原料:可能是一個取爲Ingredient實體,其中謂語是一樣的東西recipe in %@請求,%@Recipe實例列表取代。

1

的一些基本信息:

*內存操作的速度更快〜100-1000倍,然後磁盤操作。
*執行獲取請求始終是存儲(磁盤)的行程,因此會降低性能。

就你而言,你有一小組對象需要查詢信息。
簡單地迭代它們通過一個使用recipe.ingredients設置會責怪他們一個,每個接入將是商店(故障排除)之旅。

在這種情況下,預取使用(在該請求中,設置setRelationshipKeyPathsForPrefetching:預取的ingredients關係或執行提取所述一組與相應的謂詞獲取請求)。

如果需要具體的數據而已,然後使用讀取請求的方法來檢索只有你所需要的數據。
如果你打算重複訪問查詢和信息之間的關係,就去拿使用預取整組和查詢內存的


我的觀點是:

,最大限度地減少您的磁盤訪問該方法的思考(在任何情況下,你需要至少1接入)。
如果你的數據是太大,無法在內存中,或在內存中進行查詢,執行取只得到你所需要的數據。

現在:
1.Consistency - 選擇你找到舒適的方法,並堅持下去(我用預取)
2.Readability - 使用性質是更可讀然後執行查詢,但它是效率較低如果不使用預取。
3.性能 - 磁盤訪問會降低性能,但在某些情況下不可避免 4.強大 - 獲取請求表明您知道什麼最適合您的數據使用。明智地使用它。

爲了確保您最大限度地減少磁盤訪問,打開SQLite的調試上
(-com.apple.CoreData.SQLDebug)

編輯:

Faulting behaviour

+0

訪存請求並不總是涉及訪問數據存儲。核心數據維護先前提取的數據的行緩存,並且儘可能從緩存中填充提取。 – 2013-05-08 21:05:25

+0

是的,他們這樣做。嘗試一下。我會在文檔中尋找證明。如果返回的ID存在於行緩存中,那麼這些對象將用作結果,但抓取仍會到達磁盤。 – 2013-05-08 21:32:44

+1

現在我只發現這個[「每次往返存儲(每次獲取)都會產生開銷......」](http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData /Articles/cdPerformance.html#//apple_ref/doc/uid/TP40003468-SW2) – 2013-05-08 22:37:42