#19— 隨手記帳APP_Part1|CoreData資料存取&表格新增、修改、刪除&UISearchController搜尋資料功能
呈現畫面:
CoreData的使用方式網路上非常多文章,在此我就只說我認為比較特別的一些地方,不完整請見諒。
由於建立專案時有勾選“Use Core Data”的選項,Xcode就會自動幫你生成一個.xcdatamodeld檔,在裡面新增自己想記錄存取的資料(例如我imageStr是來存取圖片網址的字串)。
在AppDelegate可看到系統自動生成Core Date的程式碼
在AppDelegate內額外新增了以下程式碼(方便呼叫saveContext儲存資料)
extension NSPersistentContainer {
func saveContext () {
if viewContext.hasChanges {
do {
try viewContext.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
在SceneDelegate的scene(_:willConnectTo:options:)內新增以下程式碼
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//指定controller的container存取AppDelegate的資料
guard let _ = (scene as? UIWindowScene) else { return }
if let tabController = window?.rootViewController as? UITabBarController, let navControllers = tabController.viewControllers as? [UINavigationController] {
let appDelegate = UIApplication.shared.delegate as? AppDelegatenavControllers.forEach { (navController) in
switch navController.viewControllers[0] {
case let controller as MainTableViewController:
controller.container = appDelegate?.persistentContainer
case let controller as ChartsTableViewController:
controller.container = appDelegate?.persistentContainer
default:
break
}
}
}
}
(如此一來就可以在指定的Controller讀取AppDelegate資料,在此我的路徑UITabBarController →[UINavigationController] →指定Controller,路徑的寫法就要看你的畫面如何設計)
加了這麼多程式碼,那差異到底在哪呢?
如果不加上述那些程式碼一樣可以儲存資料,只是每當創建一個新的Controller想要儲存東西時就要先透過AppDelegate取得資料,再進行儲存
// 透過AppDelegate取得資料guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}let context = appDelegate.persistentContainer.viewContext
let itemData = ItemData(context: context)
itemData.imageStr = "圖片網址"appDelegate.saveContext()
(上下為儲存資料之差異,除此之外查詢資料、刪除、修改都能有所簡化)
var container: NSPersistentContainer!let context = container.viewContext
let itemData = ItemData(context: context)
itemData.imageStr = "圖片網址"//這裡的saveContext()是額外寫的
container.saveContext()
表格的新增、修改
利用UnwindSegue與tableView.indexPathForSelectedRow != nil的搭配,假如不是點選cell修改資訊 ,tableView.indexPathForSelectedRow就會是nil,由此判斷使用者要新增資料。
同理tableView.indexPathForSelectedRow是nil表示是新增資料,故不會傳遞資料給第二頁的itemdata屬性
判斷第二頁的屬性var itemdata:ItemData?假如為nil就是新增,有值表示要修改
表格的刪除
利用tableView(_ , commit , forRowAt)完成刪除動作,同時刪除CoreData與顯示的資料陣列
搜尋資料畫面:
在講解UISearchController搜尋資料功能前,要先了解CoreData的過濾資料功能NSPredicate,我們可以用特定的格式、參數限制取得的資料
例如:
NSPredicate(format: "category CONTAINS[c] %@","飲食")
就是限制只抓取ItemData.category =” 飲食” 的資料
了解上述功能後就能繼續實現搜尋資料功能,首先在viewDidLoad()裡新增search bar
再來使此頁Controller遵從 protocol UISearchResultsUpdating
extension SearchTableViewController:UISearchResultsUpdating{
func updateSearchResults(for searchController: UISearchController){
}
}
當我們在 search bar 輸入文字時,它將觸發 UISearchResultsUpdating 的 function updateSearchResults(for:),因此我們可在 function 裡依據 search bar 的文字調整表格對應的相關資料
參考資料: