--- tags: 新人資訊 GA: G-YWCCFEGXSJ --- [新人資訊](https://hackmd.io/@newman/portal-info) # 技術-iOS #10-Local Persistence,本地端儲存 學習主題如下: 1. 利用系統內建物件 UserDefaults,可以儲存基本類型資料,包含 array。 2. 利用系統內建 document 目錄,可以將客製物件經過 encode 轉成 plist file 型式儲存。 3. CoreData,這是由 swift 將 SQLLite 包裝轉換成物件模型的儲存模組。 先下載課程提供的專案骨架:https://github.com/appbrewery/Todoey-iOS13 ,此專案幾乎是空的,所以一開始從元件庫拉一個全新的 UIViewController,它是由一個 TableView and a Prototype Cells 組成,本專案演練的應用情境是一個 ToDo List,只需要一個頁面,所以將原本的頁面刪除,將此新頁面設成「起始頁面」,並將全來的 ViewController 更名為 TodoListViewController,並繼承系統內建的 UITableViewController。 ![](https://newprediction.blob.core.windows.net/notebook-img/7bAVZyu.png) ![](https://newprediction.blob.core.windows.net/notebook-img/ssfmxlL.png) 建立 View and Controller 的關聯: ![](https://newprediction.blob.core.windows.net/notebook-img/saNIEJ8.png) 第一種最簡單的儲存方式就是 UserDefaults,可以在 Controller 宣告總體變數 let defaults = UserDefaults.standard,將 TodoList 存在一個 itemArray (string array) 裏,項目異動時執行 self.defaults.set(self.itemArray, forKey: "TodoListArray"),在 viewDidLoad() 事件中把它讀出,達到 App 關掉後重開仍能保有資料的目的,整個應用程序非常簡單。 ![](https://newprediction.blob.core.windows.net/notebook-img/cNVMIZB.png) 第二種方式是為了儲存「客製化物件」,因為 TodoList 的項目不僅是一個字串,若要加入一個完成與否的 flag,UserDefaults 就無法支持了,因此就要比較麻煩的執行 encode 後再儲存,儲存位置也需要在系統規範有權限的位置,以下就是抓出 document directory 的方法,順便在其中塞入一個 plist file: ![](https://newprediction.blob.core.windows.net/notebook-img/uwV79LL.png) 物件定義中必須 implement protocol Codable ![](https://newprediction.blob.core.windows.net/notebook-img/BXdZj8H.png) 先要實作 TableView 相關的 method,確認資料顯示正確: ![](https://newprediction.blob.core.windows.net/notebook-img/mqtNeJY.png) 在新增按鈕觸發時跳出對話筐,確認後儲存,程式碼如下,save() 時必須經過 encode: ![](https://newprediction.blob.core.windows.net/notebook-img/OOM7vv6.png) ![](https://newprediction.blob.core.windows.net/notebook-img/6bBarJM.png) 另外新增一個互動功能,就是點選項目時,toggle done 這個欄位,並立刻儲存一次: ![](https://newprediction.blob.core.windows.net/notebook-img/Wvap3p8.png) 在 viewDidLoad() 加上 loadItems(),此時是 decode,這樣就完成應用流程。 ![](https://newprediction.blob.core.windows.net/notebook-img/E0ZC5GO.png) 執行的樣子如下: ![](https://newprediction.blob.core.windows.net/notebook-img/mlMsCgX.png) 第三種儲存方法為 Core Data,是 swift 以 SQLLite 為底層而包裝起來的物件模型,使用起來不需要關心 SQLLite 如何儲存,只要面對 Object 的世界即可。使用方法是先「新增物件模型」,以下列模板新增 file: ![](https://newprediction.blob.core.windows.net/notebook-img/QYkE32O.png) 點選 data file 會出現 swift 提供的物件結構設計畫面,把他加入兩個屬性 title and done: ![](https://newprediction.blob.core.windows.net/notebook-img/98DspVy.png) 為了在 App 啟動時引入物件模型,必須在 AppDelegate.swift import Core Data 並加入一些程式碼,因為系統提供 Core Data 的專案模版,我們可以以此模板另外新增一個測試專案,再把程式 copy 過來,可達到一樣的效果。 ![](https://newprediction.blob.core.windows.net/notebook-img/J6Y5EsL.png) 如此一來已經可以在專案中使用此物件了,相對於一般物件的建立方法,Core Data 的物件建立方法稍有不同,但也非常類似:let newItem = ItemX(context: self.context),其中 context 必須先宣告成總體變數: ![](https://newprediction.blob.core.windows.net/notebook-img/wtj02ci.png) save() 則省掉 encode 程式,顯得更精簡: ![](https://newprediction.blob.core.windows.net/notebook-img/Ui6oLCc.png) load() 程序則改成資料庫查詢語法: ![](https://newprediction.blob.core.windows.net/notebook-img/4ndM5Qv.png) 最後附帶再做一個功能:搜尋。拉一個 Search Bar 元件: ![](https://newprediction.blob.core.windows.net/notebook-img/Mu5RwJh.png) 以 extension 方式對 Controller 加入對 UISearchBarDelegate 這個 protocol 的參照,實作兩個方法如下,分別處理 search button 按下去的行爲,執行對 Core Data 資料庫的查詢,和 search text 字元變動時的行為,特別針對欄位清空時讓 UI 元件恢復起初狀態: ![](https://newprediction.blob.core.windows.net/notebook-img/IYddeDR.png) 執行狀況如下: https://youtu.be/xIRQl0hssjU 以上對 Core Data 做了基礎的演練,除此之外,本地端儲存方法還有 Realm,待下階段再續。 By Newman Chen 2022/8/28 後記 2022/8/31 試著新增一個 Entity 「Category」,並建立一對多關聯到 Item,發現 Category 名稱與內建物件重複,為避免困擾欲更名為 ItemCategory,結果似乎系統底層不允許更名,搞很久還是 compile error,稍微窺探一下後面章節 Realm,似乎是更好的本地端儲存方案,可以完全取代 Core Data 的功用,心裡差不多已經放棄 Core Data 了,砍掉吧,哈哈。