天天看點

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

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

在xcode中建立ios應用程式項目時,可以使用各種起始模闆(starting-point template)。假如要根據master-detail、utility application或empty application等模闆來建立項目,那麼隻需勾選use core data,即可在項目中使用core data。不過,grocery dude項目是根據single view application模闆建立的,它起初并沒有包含core data,筆者想通過這種方式來示範如何手工為項目添加core data支援,這樣做更有意義。為了使用core data framework,我們需要将它與項目相連結。

請按如下步驟修改grocery dude,以便将該項目與core data framework相連結:

如圖1-2所示,選中grocery dude target。

在general分頁中,點選linked frameworks and libraries區域中的“+”按鈕,然後把項目連結到coredata.framework,如圖1-2所示。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

試着檢視一下支援core data的那些内置模闆,你也許會發現:core data是在應用程式委托(application delegate)裡面設定的。本書所用的辦法是通過輔助類來設定core data,這樣的話,你就可以将這種辦法運用到自己的項目中了。這也使得core data元件變得子產品化,而且易于移植。我們将通過應用程式委托來惰性地(lazily)建立coredatahelper類的執行個體。這種執行個體可用來完成下列事項:

初始化托管對象模型

根據托管對象模型來建立持久化存儲區,并據此初始化持久化存儲協調器

根據持久化存儲協調器來初始化托管對象上下文

請根據下列步驟修改grocery dude,以便在新的xcode 組(group)裡面建立coredatahelper類:

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

右擊xcode中的grocery dude組,然後建立名為generic core data classes的新組,如圖1-3所示。

標明剛建立好的generic core data classes 組。

點選file > new > file...。

建立ios > cocoa touch > objective-c class,然後點選next按鈕。

将subclass of設為nsobject,并将class的名稱改為coredatahelper,然後點選next按鈕。

在targets中勾選“grocery dude”,然後點選create按鈕,這樣就會在grocery dude項目的目錄中建立coredatahelper類了。

程式清單1-1列出了需要添加到coredatahelper頭檔案中的新代碼。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

作為objective-c程式員,你應該已經熟悉頭檔案(也就是.h檔案)的用途了。coredata-helper.h用來聲明coredatahelper中的context、model、coordinator及store等屬性。當應用程式委托建立coredatahelper執行個體的時候,系統會調用setupcoredata方法。若要把托管對象上下文裡發生的變更儲存到持久化存儲區,則可調用savecontext方法。假如要寫入磁盤的資料比較多,那麼該方法會導緻使用者界面卡頓。第11章将給程式添加背景儲存功能,而在這之前,筆者建議你隻從appdelegate.m的appli-cationdidenterbackground及applicationwillterminate方法裡面調用它。

請按照下述步驟修改grocery dude,以配置coredatahelper的頭檔案:

用程式清單1-1中的代碼把coredatahelper.h檔案裡現有的全部代碼都替換掉。假如現在檢視coredatahelper.m檔案,那麼xcode會提示你setupcoredata及savecontext方法還沒實作,不過目前這無關緊要。

這個輔助類一開始會有四個主要的部分,它們分别叫做files、paths、setup及saving。為了便于檢視及閱讀代碼,筆者用編譯訓示标記(pragma mark)将這些區域分隔開。編譯訓示标記使得程式員可以按照邏輯來組織源碼,而且xcode還會據此生成一份漂亮的菜單,以供使用者在不同的部分中浏覽。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

coredatahelper.m的files 部分中會有一個nsstring,用于存儲持久化存儲區的檔案名。如果稍後還要添加其他持久化存儲區,那麼也應該在這裡寫下它們的檔案名。程式清單1-2中的代碼包含一條#define語句,grocery dude中的絕大多數類都要使用這行語句,它是為了協助調試工作而設的。如果debug是1,那麼該類的debug logging(調試日志記錄)功能就會開啟。本書大部分的nslog指令都包裹在if(debug==1)語句裡,是以隻有開啟了調試功能之後,那些指令才會有效果。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下述步驟修改grocery dude,以便添加files部分:

把程式清單1-2中的代碼添加到coredatahelper.m檔案底部,但是要将其置于@end語句之前。

為了把資料以持久化的形式寫入磁盤,core data需要知道持久化存儲檔案在檔案系統中的位置。我們可以分别編寫3個方法來向core data提供這一資訊。程式清單1-3列出了第一個方法,也就是applicationdocumentsdirectory方法,該方法傳回nsstring,而這個nsstring就代表應用程式文檔目錄的路徑。你會注意到我們這是首次把調試代碼包裹在if(debug==1)語句裡面,這種調試代碼用于顯示目前運作的究竟是哪個方法。nslog語句很适合用來列印應用程式裡各個方法的執行順序,而這對調試工作很有幫助。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便添加paths部分:

将程式清單1-3中的代碼添加到coredatahelper.m檔案尾部,并放在@end語句之前。

接下來這個方法叫做applicationstoresdirectory,它會向應用程式文檔目錄中添加名為stores的子目錄,并且将其路徑放在nsurl中傳回。若stores目錄尚未建立,則程式清單1-4中的相關代碼會将其建立出來。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便将applicationstoresdirectory方法添加到paths 部分中:

将程式清單1-4中的代碼添加到coredatahelper.m檔案尾部,并放在@end語句之前。

最後一個方法如程式清單1-5所示,它隻是把持久化存儲區的檔案名添加到stores目錄的路徑中。調用完該方法之後,我們就可以知道持久化存儲檔案的完整路徑了。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便将storeurl方法添加到paths部分中:

将程式清單1-5中的代碼添加到coredatahelper.m檔案尾部,并放在@end語句之前。

處理完檔案和路徑之後,現在該實作初始化core data所用的三個方法了。程式清單1-6列出了第一個方法,它的名字叫做init,程式在建立coredatahelper執行個體的時候,會自動運作該方法。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

_model執行個體變量指向nsmanagedobjectmodel對象。這個對象是我們在nsmana-gedobjectmodel類上以nil為參數調用mergedmodelfrombundles方法而得來的,該方法會用main bundle中的全部資料模型檔案(data model file,也就是對象圖)來初始化此對象。目前項目裡還沒有模型檔案,但是第2章就會加進來一個。如果有多個模型需要合并,那麼可以把元素類型為nsbundles的nsarray數組傳給merged-modelfrombundles,但一般來說不用擔心這個問題。

還有一種辦法也能初始化托管對象模型,就是明确寫出需要使用的模型檔案。與直接合并bundle相比,這種寫法的代碼量多了一倍。可以用這條語句來手工指定模型:_model=[[nsmanagedobjectmodel alloc] initwithcontents-ofurl: [[nsbundle mainbundle] urlforresource:@"model" withexten-sion:@"momd"]];。

_coordinator執行個體變量指向nspersistentstorecoordinator對象。剛才我們曾經建立了托管對象模型,并令_model指向該模型,而現在我們就根據這個_model指針來初始化nspersistentstorecoordinator。持久化存儲協調器裡面目前還沒有持久化存儲檔案,這些檔案稍後将由setupcoredata方法加入。

_context執行個體變量指向nsmanagedobjectcontext對象。在初始化該對象的時候,我們把并發類型設為nsmainqueueconcurrencytype,意思是令這個上下文在主線程隊列中運作。凡是要編寫資料驅動型的使用者界面,就需要将上下文放在主線程中。把上下文初始化好之後,我們用剛才那個指向nspersistentstorecoordinator的_coordinator指針來配置它。第8章将會示範如何使用多個托管對象上下文,而且還會介紹與背景運作相對應的nsprivatequeueconcurrencytype,不過目前我們把上下文放在主線程裡就可以了。

請按下列步驟修改grocery dude,以便添加setup部分:

将程式清單1-6中的代碼添加到coredatahelper.m檔案底部,并放在@end語句之前。

setup 部分裡還需要另外一個方法—loadstore方法,其代碼如程式清單1-7所示。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

loadstore方法很簡單。首先判斷_store是不是已經加載好了,如果還沒有,那就聲明一個指向nserror執行個體的error指針,并将其目前值設為nil。稍後在設定_store執行個體變量的時候,我們會用該指針來捕獲設定過程中所發生的錯誤。假如在執行完配置代碼之後,_store是nil,那就表明配置操作失敗了,我們把發生的錯誤及其内容記錄到控制台。

通過addpersistentstorewithtype方法将sqlite持久化存儲區添加到_coordinator之後,_store變量的值就是指向這個持久化存儲區的指針。而調用addpersistent-storewithtype方法時所使用的storeurl參數則是由早前建立的storeurl方法所傳回的。

請按下列步驟修改grocery dude,以便将loadstore方法添加到setup 部分中:

把程式清單1-7中的代碼添加到coredatahelper.m檔案底部,并放在@end語句之前。

最後我們來建立setupcoredata方法。由于其他的輔助方法已經就位,是以這個方法寫起來非常簡單。程式清單1-8列出了這個新方法的代碼,目前它隻需調用loadstore即可。本書稍後将為程式加入更多的功能,到那時,該方法也會随之擴充。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便将setupcoredata方法添加到setup部分中:

把程式清單1-8中的代碼添加到coredatahelper.m檔案底部,并放在@end語句之前。

接下來我們要實作的這個方法可以把_context中所發生的變更儲存到_store裡。具體做法很簡單:隻需像程式清單1-9這樣,給上下文發送save:消息即可。我們将建立名為saving的部分,并把savecontext方法置于其中。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便添加saving部分:

把程式清單1-9中的代碼添加到coredatahelper.m檔案底部,并放在@end語句之前。

現在我們應該來試用一下這個coredatahelper了!為了使用該類,首先需要在應用程式委托的頭檔案(header)中添加新的屬性。另外,還需引入coredatahelper,使頭檔案能夠知道我們剛寫好的這個類。程式清單1-10用粗體标出了應用程式委托的頭檔案中所需修改的代碼。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便将coredatahelper添加到應用程式委托中:

用程式清單1-10中的代碼替換appdelegate.h的原有内容。

下一步是修改應用程式委托的實作檔案,把名為cdh的小方法放入其中,該方法會傳回“非nil”的coredatahelper執行個體。另外,為了便于調試,我們還添加了一行“#define debug 1”語句,如程式清單1-11所示。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以便将cdh方法添加到應用程式委托之中:

把程式清單1-11裡的代碼添加到appdelegate.m檔案中的“@implementation appdelegate”這一行下面。

本小節的最後一步需要確定當應用程式轉入背景或終止時,上下文裡面的内容能夠得以儲存。這是個将資料寫入磁盤的好機會—此時寫入資料,不會導緻使用者界面反應遲緩,因為使用者界面本身已經隐藏起來了。程式清單1-12列出了與上下文的儲存操作有關的代碼。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援

請按下列步驟修改grocery dude,以確定應用程式在轉入背景或終止時上下文中的資料能夠得以儲存:

1.把[[self cdh] savecontext];這行語句添加到appdelegate.m檔案的applicationdidenterbackground方法裡。

2.把[[self cdh] savecontext];這行語句添加到appdelegate.m檔案的applicationwillterminate方法裡。

在ios 仿真器中運作grocery dude程式,然後按下home鍵(可以通過“shift++h”組合鍵或ios 仿真器的hardware>home菜單項來模拟“按下home鍵”這一操作),并同時檢視調試 日志視窗。隻有真正用到core data的時候,應用程式才會通過應用程式委托的cdh方法設定它,于是,在剛開始運作程式的時候,日志裡面并沒有内容。首次使用core data是在調用save:的時候,也就是應用程式轉入背景的時候。本書在後續章節中還會不斷地完善這個應用程式,而cdh方法的調用時機也會有所提前。圖1-5示範了按下home鍵之後各方法的執行順序。

《Core Data應用開發實踐指南》一1.4 為現有的應用程式添加Core Data支援