天天看點

《Core Data應用開發實踐指南》一2.13 擷取托管對象

本節書摘來自華章出版社《core data應用開發實踐指南》一書中的第2章,第2.13節,作者 (美)tim roadley,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

想操作托管對象上下文中的現有資料,就必須先把它擷取(fetch)過來。假如待擷取的資料沒有放在上下文裡,那麼core data會從底層的持久化存儲區裡把它拿出來,這個過程對開發者來說是透明的。要執行擷取操作,就得有nsfetchrequest執行個體,該執行個體會傳回nsarray,這個數組裡面的元素都是托管對象。在執行擷取操作的時候,nsfetchrequest會根據特定的實體,把每個托管對象都放在nsarray這個數組中,并将其傳回給調用者。用sql資料庫領域的術語來說,擷取操作類似于select語句。相關代碼如程式清單2-4所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

請按照下列步驟修改grocery dude,以便擷取item實體的所有執行個體:

把程式清單2-4中的代碼添加到appdelegate.m檔案的demo方法裡面。

運作程式并注意控制台中輸出的日志,你将會看到12行非常相似的資訊,每一行資訊都代表從資料庫中取出的一個托管對象。假如你的資料庫裡有重複資料,那麼具體的行數可能和書中列出的有所不同。圖2-10示範了正常運作程式時所産生的結果。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

如果想檢視每個托管對象的特性值,那麼可以用for循環來周遊nsarray,并用nslog把每個item的name特性值列印出來。相關代碼如程式清單2-5所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

請按下列步驟修改grocery dude,以便在控制台的日志中顯示出每個item的name:

把appdelegate.m檔案的demo方法改為程式清單2-5的樣子。方法開頭的nslog語句可以保留,也可以删掉。

重新運作應用程式,并觀察控制台中的日志,現在應該可以看到每個托管對象的name特性值了。正常的運作效果如圖2-11所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

nsfetchrequest執行完畢之後,會傳回nsarray,而nsarray本身就支援對其中的元素進行排序。另外,我們也可以換一種辦法,就是給nsfetchrequest配置排序描述符(sort descriptor),這樣的話,nsfetchrequest就可以直接按特定方式對擷取到的托管對象進行排序了。這個排序描述符是作為nssortdescriptor的執行個體傳給nsfetchrequest的。用sql資料庫的術語來說,排序描述符就類似于order by語句。程式清單2-6列出了相關代碼。

《Core Data應用開發實踐指南》一2.13 擷取托管對象
《Core Data應用開發實踐指南》一2.13 擷取托管對象

請按下列步驟修改grocery dude,以便對擷取到的托管對象進行排序:

修改appdelegate.m檔案的demo方法,用程式清單2-6中的粗體代碼把原有的相關代碼替換掉。

再次運作應用程式,并檢視控制台中的日志,你會發現托管對象已經按照其名稱的字母順序排列好了。正常的運作效果如圖2-12所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

有時我們并不想把與某個實體有關的全部對象都擷取過來,這時可以通過謂詞來篩選。我們采用nspredicate執行個體來定義謂詞,并将其傳給nsfetchrequest執行個體。有了謂詞之後,擷取請求就會根據謂詞中的标準來限定擷取到的托管對象的數量。由于謂詞與具體的持久化存儲區無關,是以不論後端采用何種存儲區,都可以使用相同的謂詞來篩選它。但是,在特殊情況下,某些謂詞無法适用于特定格式的存儲區。比方說,matches操作符可以對in-memory存儲區執行篩選,卻不能用在sqlite格式的存儲區上。以sql資料庫的術語來說,謂詞類似于where子句。

在擷取請求的執行過程中,系統要根據每個托管對象來對謂詞分别求值。謂詞的求值結果是個boolean值。如果是yes,那就表明該托管對象符合謂詞中的标準,于是也就可以留在最終的擷取結果中;但若是no,則表示該對象不符合謂詞中的标準,于是就會從最終的擷取結果中剔除。

執行完nsfetchrequest之後,擷取到的結果會存放在nsarray裡面,此時就可以按照自己的需要對這個數組裡面的托管對象進行篩選了。可以用nsarray的filteredarrayusingpredicate方法來篩選,也可以用nsmutablearray的filter-usingpredicate方法執行就地篩選。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

請按下列步驟修改grocery dude,向其中添加謂詞,以便篩選擷取到的托管對象:

修改appdelegate.m檔案的demo方法,用程式清單2-7中的粗體代碼把原有的相關代碼替換掉。

運作應用程式,并觀察控制台中的日志,你應該會發現:在列出的貨品名稱中,已經沒有coffee這一項了。正常的運作結果如圖2-13所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

假如每次擷取托管對象時都要手工編寫謂詞格式确實很累人,幸好xcode的data model designer有預定義擷取請求的功能。這些可複用的模闆比謂詞更容易配置,而且還能減少重複代碼。隻需根據應用程式的模型來操作一系列下拉清單框及文本框,即可配置好一份擷取請求模闆。但如果要自定義and、or這樣的邏輯組合,那麼這個模闆就無法滿足要求了,此時仍然需要通過代碼來指定謂詞。

請按下列步驟修改grocery dude,以建立擷取請求模闆:

選中model.xcdatamodeld。

點選editor>add fetch request菜單項。

把擷取請求模闆的名稱設為test。

點選“+”按鈕來配置名為test的擷取請求模闆,如圖2-14所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

要想使用擷取請求模闆,需要先給托管對象模型發送消息,告訴它将要使用的模闆叫什麼名字。發送完消息之後,就可以在傳回的nsfetchrequest上面操作了。由于這種擷取請求是根據模闆建立出來的,是以開發者無需通過向其發送謂詞來執行篩選操作。假如想修改這種擷取請求(比方說,要對其進行排序),那麼必須先制作它的一份拷貝,這是因為擷取請求模闆是根據不可變的模型(immutable model或unchangeable model)建立出來的。相關代碼如程式清單2-8所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

請按下列步驟修改grocery dude,以便使用名為test的擷取請求模闆:

修改appdelegate.m檔案中的demo方法,用程式清單2-8中的代碼替換原有的代碼。程式清單2-8中的那行粗體代碼是新加進來的,另外,修改過的代碼中是沒有謂詞的。

運作應用程式,并觀察控制台中的日志,你會發現這些托管對象均已按照名稱排過序,而且隻有名稱中包含字母e的對象才會出現在控制台中,這些效果都是通過配置擷取請求模闆而實作出來的。正常的運作結果如圖2-15所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象

不知你是否注意到了系統為這次fetch操作所生成的sql語句。這條sql語句的意思就是對擷取到的各個item進行篩選與排序(“擷取”對應于語句中的“select”;“篩選”對應于語句中的“where”;“排序”對應于語句中的“order by”)。正常的運作效果如圖2-16所示。

《Core Data應用開發實踐指南》一2.13 擷取托管對象