功能方法
下面我们来创建一些念头笔记用到的方法,在之前的章节中我们实现了新建笔记的功能,但当我们每次重新打开APP时,它又会“恢复”到初始模式,在上一次操作的数据全部清空了。
这是因为我们只是完成了简单的操作而已,而没有实现其核心功能,即把数据存起来。但是我们没有数据库也没有云端,数据存在哪里呢?是的,放在本地,放到本地缓存起来。
在我们创建iOS
项目时,系统会创建一个plist
文件,作为缓存区,我们可以将数据暂时存储在这里。
加载数据
在ViewModel
类中,我们需要使用到的基本方法如下代码所示:
//初始化 init() { loadItems() saveItems() } // 获取设备上的文档目录路径 func documentsDirectory() -> URL { FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] } // 获取plist数据文件的路径 func dataFilePath() -> URL { documentsDirectory().appendingPathComponent("IdeaNote.plist") } // 将数据写入本地存储 func saveItems() { let encoder = PropertyListEncoder() do { let data = try encoder.encode(noteModels) try data.write(to: dataFilePath(), options: Data.WritingOptions.atomic) } catch { print("Error writing items to file: (error.localizedDescription)") } } // 从本地存储加载数据 func loadItems() { let path = dataFilePath() if let data = try? Data(contentsOf: path) { let decoder = PropertyListDecoder() do { noteModels = try decoder.decode([NoteModel].self, from: data) } catch { print("Error reading items: (error.localizedDescription)") } } }
上述代码中,首先创建了一个方法documentsDirectory
获取设备上的文档目录路径,再指定要获取的目录IdeaNote.plist
的方法dataFilePath
。
获得本地设备目录后,使用saveItems
方法将noteModels
数组中的数据写入到到本地存储中,当App打开的时候,使用loadItems
方法让List
列表从本地存储中加载数据遍历列表。
最后在我们App初始化加载的时候,调用loadItems
加载数据方法,并调用saveItems
方法将数据写入缓存中。
以上是加载本地数据的基本方法。
增删改查
紧接着,我们来实现念头笔记的增删改查的基本方法,如下代码所示:
// 创建笔记 func addItem(writeTime: String, title: String, content: String) { let newItem = NoteModel(writeTime: writeTime, title: title, content: content) noteModels.append(newItem) saveItems() } // 获得数据项ID func getItemById(itemId: UUID) -> NoteModel? { return noteModels.first(where: { $0.id == itemId }) ?? nil } // 删除笔记 func deleteItem(itemId: UUID) { noteModels.removeAll(where: { $0.id == itemId }) saveItems() } // 编辑笔记 func editItem(item: NoteModel) { if let id = noteModels.firstIndex(where: { $0.id == item.id }) { noteModels[id] = item saveItems() } } // 搜索笔记 func searchContet() { let query = searchText.lowercased() DispatchQueue.global(qos: .background).async { let filter = self.noteModels.filter { $0.content.lowercased().contains(query) } DispatchQueue.main.async { self.noteModels = filter } } }
由于列表中每一行的数据都有对应的ID,因此除了新增数据以外,删改查的基本功能都是通过数据的ID操作的,计算机都是先找到数据,再对数据进行操作。
新建笔记的方法addItem
,通过传入对应参数的值,然后将参数的值赋值给NoteModel模型类,再通过append
添加的方法添加到noteModels数组中,最后调用saveItems方法保存到本地。
删除笔记的方法deleteItem
,需要先获取到指定行数据的ID,这里抽离出了获得数据ID的方法getItemById,通过传入数据ID与NoteModel模型类的ID进行匹配就可以知道是哪一条数据,再调用removeAll
删除noteModels数组中指定ID的数据,最后调用saveItems方法保存操作。
编辑笔记的方法editItem
,也是传入符合NoteModel模型类的数据,找到它的ID,最后调用saveItems方法保存到本地。
搜索笔记的方法searchContet
,先定义用户搜索内容为searchText,再拿用户输入的内容和noteModels数组中的content内容数据做对比,如果符合,就返回符合的数据到noteModels数组中。
其他方法
除此之外,我们将原来在新建笔记页面使用到的获得当前时间的方法,包括判断输入内容是否为空的方法也纳入到ViewModel
里面,如下代码所示 :
// 获取当前系统时间 func getCurrentTime() -> String { let dateformatter = DateFormatter() dateformatter.dateFormat = "YYYY.MM.dd" return dateformatter.string(from: Date()) } // 判断文字是否为空 func isTextEmpty(text:String) -> Bool{ if text == "" { return true } else { return false } }
判断内容是否为空的方法是传入一个参数值,通过判断是否为空,从而返回一个Bool类型的值,后面我们用来判断输入的标题和内容是否为空。
App使用
创建好ViewModel后,当我们要使用它,需要在IdeaNoteApp
项目页面声明好使用的ViewModel,如下代码所示:
import SwiftUI @main struct IdeaNoteApp: App { @StateObject var viewModel: ViewModel = ViewModel() var body: some Scene { WindowGroup { ContentView() .environmentObject(viewModel) } } }
IdeaNoteApp
页面是整个App启动时的页面,它相当于我们的主函数,当前项目指向的首页是ContentView
首页视图,因此在使用MVVM
项目开发模式时,当我们用使用到ViewModel
时,就需要引用ViewModel到主函数中方可使用。
本章小结
恭喜你,准备工作已经就绪,随时可以开始下一步的内容。
当然,为了让大家更好地吸收学习内容,本章我们就分享了如何完成Model、View Model部分,下一章节中,我们将继续完成View视图的相关内容,我们将在原来View视图的基础上进行内容调整,方便大家更好地理解SwiftUI的运作模式。
快来动手试试吧~