iOS開發之表檢視愛上CoreData

青玉伏案發表於2015-12-14

  在接觸到CoreData時,感覺就是蘋果封裝的一個ORM。CoreData負責在Model的實體和sqllite建立關聯,資料模型的實體類就相當於Java中的JavaBean, 而CoreData的功能和JavaEE中的Hibernate的功能類似,最基本是兩者都有通過對實體的操作來實現對資料庫的CURD操作。CoreData中的上下文(managedObjectContext)就相當於Hibernate中的session物件, CoreData中的save操作就和Hibernate中的commit,還有一些相似之處,在這就不一一列舉了。(上面是筆者自己為了更好的理解CoreData而做的簡單類比,如果學過PHP的ThinkPHP框架的小夥伴們也可以和TP中的ORM類比)。

那麼TableView為什麼會愛上CoreData呢?下面會通個程式碼給出他們相愛的原因。就舉一個IOS開發中的經典的demo:通訊錄來說明問題。

1.在TableView沒遇到CoreData的時候我們怎麼通過動態表檢視來顯示我們的通訊錄的內容呢?也就是說我們通訊錄的資料結構該如何組織呢?

為了在TableView中顯示我們的資訊我們這樣設計我們的資料結構:

1.整個TableView是一個可變的陣列tableArray;

2.tableArray中的每個元素又是一個存放分組的字典sectionDictionary;

3.在sectionDictionary中我們存放著兩個鍵值對 header和items, header中存放的時section中的名字,items中存放的時每個section中的使用者資訊

4.items中又是一個陣列rowsArray, rowsArray中存放的又是一個字典userInfoDictionary, 在userInfoDictionary中存放著我們要顯示的資訊

千字不如一圖,看到上面對我們要設計的資料結構的描述會有點迷糊,下面來張圖吧:

2.資料結構我們設計好了,那麼如何用程式碼生成我們的測試資料(資料的組織形式如上圖所示),下面的程式碼就是生成我們要在tableView中顯示的資料,生成的陣列儲存在tableArray中,程式碼如下:

 

4.上面給出的時關鍵程式碼,至於怎麼配置TableView的Cell模板或者如何把TableViewController和Storyboard中的ViewController繫結,在前面的部落格中都有介紹,在這小編就不做贅述。執行結果和上面的圖片是一樣的。

  上面的東西只是這篇博文的引子,為了顯示上面的資料結構我們這樣做是不是太麻煩了,而且上面的資料是不能被持久化儲存的。如果給我們的資料都要轉換成上面的資料組織形式,想必由於所給資料結構的不確定,所以轉換起來是相當的複雜的。TableView之所以會愛上CoreData,是因為我們的CoreData會簡化我們對資料的操作,並且會持久化到sqlite中。CoreData相當於TableView和sqllite的紐帶,說的專業一些就是對映,那麼我們CoreData如何使用才會簡化我們的操作呢?下面將要介紹的才是這篇部落格中的重點:我們如何使用CoreData才會讓TableView愛上它呢?

1.新建一個Empty Application, 在新建工程的時候,不要忘了把Use Core Data給選中,選中Use Core Data會自動引入Core Data框架庫和在AppDelegate.h和AppDelegate.m中進行相應的配置,並且同時還自動生成一個以本應用名命名的Data Model檔案,我們可以在Data Model檔案中新增我們的資料模型, 新增好的資料模型我們會在生成資料實體類時使用(和JavaBean類似)

(1)AppDelegata.m中多出的部分程式碼如下,從多出的部分程式碼就可以看出,CoreData會把我們的資料實體和sqllite建立起一一對應的關係:

(2)我們可以通過 projectName.xcdatamodeld中建立我們的資料實體模型,如下圖所示

 

(3)通過建立好的資料實體模型來建立我們的實體類(和JavaBean類似的東西)建立過程如下圖,點選下一步以後,選中建立的實體模型即可:

 

2.CoreData準備的差不多啦,該我們的TableView出場啦,在Empty Application中預設的時沒有storyboard, 如果你又想通過storyboard來簡化你的操作,得給應用建立一個storybaord才對,建立過程如下:

(1)第一步建立一個storyboard檔案,命名為Main,如下圖所示

 

(2)第二步:設定從storyboard來啟動, 在Main InterFace中選中我們建立的storyboard即可

 

(3) 第三步修改AppDelegate.m中的函式如下所示,把初始化的工作交給我們建立的storyboard進行:

 3.配置工作完成接下來就是TableView和CoreData相愛的過程啦,如何在storyboard中對TableView的cell進行配置在這兒就不贅述了,下面給出我們要通過TableView和CoreData來實現什麼功能。

(1)我們要實現對通訊錄的增刪改查,主要需求入下圖所示:

(2)實現新增功能,點選右上角的新增按鈕時會跳轉到新增頁面,在新增頁面中有兩個TextField來接受使用者的輸入,點選新增按鈕進行資料新增。AddViewController.m中的主要程式碼如下。

a.需要用到的屬性如下, 用NSManagedObejectContext的物件來操作CoreData中的資料,和Hibernate中的session的物件相似

b.獲取UIApplication的單例application, 然後再通過application獲取delegate, 最後通過delegate來獲取上下文,程式碼如下:

​    c.編輯點選button要回撥的方法,在點選新增按鈕時首先得通過上下文獲取我們的實體物件,獲取完實體物件後再給實體物件的屬性賦上相應的值,最後呼叫上下文的save方法來儲存一下我們的實體物件。新增完以後還要通過navigationController來返回到上一層檢視,程式碼如下

​  (3)實現上面的程式碼只是通過CoreData往sqlite中新增資料,要想在我們的TableView中顯示還需要通過CoreData把我們的儲存在sqlite中的資料來查詢出來,再用CoreData給我們提供的方法把查詢結果做一個轉換,轉換成適合TableView顯示的資料,下面給出相應的獲取資料的程式碼。

a.在TableViewController我們需要宣告如下兩個屬性,一個用於獲取上下文,一個用於儲存返回結果

c.在viewDidLoad中通過上下文來查詢資料,並儲存在fetchedResultsController中, 在獲取資料的過程中我們需要定義UIFetchRequest 和排序規則,程式碼如下:

(4) 經上面的程式碼,我們就可以通過CoreData查詢sqlite, 然後把查詢測資料結果顯示到TableView中,可是上面的程式碼有個問題,就是當通過CoreData來修改或著新增資料時,TableView上的內容是不跟著CoreData的變化而變化的,接下來要做的就是要繫結TableView和CoreData的關係。即通過CoreData修改資料的同時TableView也會跟著改變。

a.要想實現TableView和CoreData的同步,我們需要讓TableView對應的Controller實現協議NSFetchedResultsControllerDelegate, 然後再ViewDidLoad中進行註冊,在新增上相應的回撥程式碼即可。實現協議的程式碼如下:

b.進行委託回撥的註冊,在viewDidLoad中新增

c.新增相應的委託回撥的方法,我們可以到Help中的API中去複製, 查詢NSFetchedResultsControllerDelegate,找到相應的回撥程式碼複製過來然後再做簡單的修改即可, 實現回撥的方法程式碼如下:

(5)經過上面的程式碼就可以實現CoreData和TableView的同步啦,到此會感覺到TableView結合著CoreData是如此的順手,雖然配置起來較為麻煩,但還是比較中規中矩的,只要按部就班的來,是不難實現的。因此TableView深愛著CoreData. 上面我們完成了通過CoreData來對資料的插入和查詢並同步到TableView中,下面將會介紹到如何對我們的Cell進行刪除。

a.想通過TableView來刪除資料的話得開啟我們的TableView的編輯功能

​    b.開啟編輯功能以後我們就可以在tableView的對應的方法中來實現刪除功能啦,當點選刪除時,我們需呀獲取cell對應的索引在CoreData中的實體物件,然後通過上下文進行刪除,在save一下即可。因為CoreData和TableView已經進行了同步,所以刪除後TableView會自動更新,刪除程式碼如下:

​    c.預設的刪除按鈕上顯示的是Delete, 可以通過下面的方法進行修改,程式碼如下:

(6)到這一步刪除功能算是完成了,還有最後一個功能點,就是更新我們的資料。更新資料通過點選相應的cell,把cell上的資料傳到UpdateView的頁面上,然後進行更新即可。

a.下面的程式碼是獲取資料我們選中的資料並通過KVC把引數傳到目的檢視中

b.在UpdateViewController中把傳過來的實體物件進行更新,再儲存。更新部分的程式碼和新增部分的程式碼差不多,在這就不往上貼啦。

經過上面的艱苦的歷程後我們的tableView就會深深的愛上CoreData, 可能上面的內容有些多,有疑問的可以留言交流。

 

 

  上面所做的功能裡我們的真正的通訊錄還有些差距,看過上面的程式碼的小夥伴會有個疑問:新增的頁面和更新的頁面能不能使用同一個呢? 當然啦,為了遵循Don`t Repeat Yourself的原則,下面我們就把兩個相似的頁面合併在一起,同時給我們每條記錄加上頭像和給整個tableView加上索引。

1.把更新頁面刪掉,做如下修改,點選新增和修改都跳轉到我們的編輯頁面,同時新增一個自定義Button,點選Button時,我們會呼叫ImagePickerController來從手機相簿獲取圖片:

2.為了把頭像持久化儲存,我們還得修改資料模型,從新生成Person類,新增一個儲存image的選項,是通過二進位制的形式儲存的

3.在之前儲存的ViewController中如果Person為空,說明是執行的新增記錄的方法我們就生成一個新的person, 如果Person不為空則不新建Person物件,直接更新完儲存。

(1)為了獲取圖片,我們需要新增ImagePickerController物件,並在viewDidLoad中做相應的配置,程式碼如下

進行相關配置

(2)點頭像會跳轉到我們定義好的ImagePickerController中,我們就可在圖片庫中選取相應的照片啦。

(3)在ImagePickerController中點選取消按鈕觸發的事件,跳轉到原來編輯的介面

(4)選完圖片把頭像設定成使用者選中的按鈕,並dismiss到原來介面

 

(5)把我們點選儲存按鈕回撥的方法作如下修改,如果person為空,我們會新建一個新的person.

 

 

(6)因為是何更新頁面公用的所以我們要在viewDidLoad對TextField和Button的背景進行初始化,如果person中的imageData有值我們有用傳過來的圖片,否則用預設的圖片,新增資料初始化程式碼如下:

4.上面的程式碼就可以插入頭像了,我們需要在tableView中進行顯示即可,在tableView中從person物件中獲取相應的頭像,然後顯示即可,下面我們要加上索引。

(1)在cell中顯示頭像的程式碼如下:

(2)實現新增索引回撥的方法

經過上面的步驟,我們之前倆個頁面可以共用,而且加上了頭像和索引,執行效果如下:

 

上面的內容挺多的啦吧,彆著急,我們的這個通訊錄還沒完呢,通訊錄中的查詢功能是少不了的,因為當存的使用者多了,為了方便使用者查詢我們還需要新增一個控制元件。接下來是我們Search Bar and Search 出場的時候了。UISearchDisplayController自己有一個TableView用於顯示查詢出來的結果,需要在通訊錄中新增一些程式碼我們的Seach Bar就可以使用了。

1.在storyboard中新增Search Bar and Search,然後把屬性拖入我們對應的TableViewController中即可,新新增屬性如下:

2.編輯SearchBar內容改變後呼叫的方法,我們會通過使用者輸入的內容進行一個模糊查詢,把查詢的內容新增到我們之前的fetchResultController中

 

3.因為UISearchDisplayController裡的TableView和我們之前的tableView用的是一個FetchedReaultsController,所以在UISearchDisplayController取消的時候要過載一下我們之前的TableView,或去通訊錄中的FetchedResultsController, 程式碼如下:

 

4.因為通過search查詢的結果集會顯示在UISearchDisplayController自己的tableView中,所以載入cell時要進行相應的選擇,search中的cell是我們自定義的cell, 選擇程式碼如下:

 

5.在我們的查詢後的列表中,如果還想點選cell以後跳轉到編輯頁面,我們該如何做呢? 新增下面的回撥方法,用程式碼進行跳轉,程式碼如下:

 

經過上面的步驟,我們的查詢功能就寫好了,下面是最終的執行結果:

經上面這麼曲折的過程,我們的通訊錄的基本功能就差不多了。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

iOS開發之表檢視愛上CoreData

相關文章