天天看點

iOS開發之表視圖愛上CoreData

  在接觸到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中存放着我們要顯示的資訊

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

iOS開發之表視圖愛上CoreData

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

    3.把我們用代碼建立的模拟資料在我們的tableview中進行顯示,在相應的函數中根據我們生成的資料傳回相應的值顯示在tableview中,顯示代碼如下:

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中建立我們的資料實體模型,如下圖所示

iOS開發之表視圖愛上CoreData

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

iOS開發之表視圖愛上CoreData

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

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

iOS開發之表視圖愛上CoreData

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

iOS開發之表視圖愛上CoreData

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

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

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

iOS開發之表視圖愛上CoreData

  (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我們需要聲明如下兩個屬性,一個用于擷取上下文,一個用于存儲傳回結果

                                          

    b.​在viewdidload中擷取上下文

    c.在viewdidload中通過上下文來查詢資料,并存儲在fetchedresultscontroller中, 在擷取資料的過程中我們需要定義uifetchrequest 和排序規則,代碼如下:

    d.把查詢到的資料顯示在tableview中代碼如下:

  (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來從手機相冊擷取圖檔:

iOS開發之表視圖愛上CoreData

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

iOS開發之表視圖愛上CoreData

  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

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