实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)(2)

简介: 实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)

功能方法

下面我们来创建一些念头笔记用到的方法,在之前的章节中我们实现了新建笔记的功能,但当我们每次重新打开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)")
            }
        }
    }

image.png

上述代码中,首先创建了一个方法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
            }
        }
    }

image.png

由于列表中每一行的数据都有对应的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
        }
    }

image.png

判断内容是否为空的方法是传入一个参数值,通过判断是否为空,从而返回一个Bool类型的值,后面我们用来判断输入的标题和内容是否为空。

App使用

创建好ViewModel后,当我们要使用它,需要在IdeaNoteApp项目页面声明好使用的ViewModel,如下代码所示:

import SwiftUI
@main
struct IdeaNoteApp: App {
    @StateObject  var viewModel: ViewModel = ViewModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(viewModel)
        }
    }
}

image.png

IdeaNoteApp页面是整个App启动时的页面,它相当于我们的主函数,当前项目指向的首页是ContentView首页视图,因此在使用MVVM项目开发模式时,当我们用使用到ViewModel时,就需要引用ViewModel到主函数中方可使用。

本章小结

恭喜你,准备工作已经就绪,随时可以开始下一步的内容。

当然,为了让大家更好地吸收学习内容,本章我们就分享了如何完成Model、View Model部分,下一章节中,我们将继续完成View视图的相关内容,我们将在原来View视图的基础上进行内容调整,方便大家更好地理解SwiftUI的运作模式。

快来动手试试吧~

相关文章
|
1月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
88 3
|
1月前
|
iOS开发 开发者
一键制作 iOS 上架 App Store 描述文件教程
一键制作 iOS 上架 App Store 描述文件教程
|
1月前
uni-app 185iOS端兼容处理
uni-app 185iOS端兼容处理
36 1
|
1月前
|
Android开发 iOS开发 开发者
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
97 0
|
5天前
|
存储 编解码 JSON
利用SwiftUI构建高效iOS天气应用
【4月更文挑战第21天】 在本文中,我们将深入探讨如何运用SwiftUI框架打造一个响应迅速且用户友好的iOS天气应用程序。我们将重点放在利用SwiftUI的声明式语法简化界面开发,并通过结合Core Location和Networking APIs实现实时天气数据的获取与展示。文章将详细阐述整个开发过程,包括API集成、数据模型设计、用户界面布局以及动态适配不同屏幕尺寸的策略。
|
24天前
|
开发工具 Swift iOS开发
利用SwiftUI构建动态用户界面:iOS开发新范式
【4月更文挑战第3天】 随着苹果不断推进其软件开发工具的边界,SwiftUI作为一种新兴的编程框架,已经逐渐成为iOS开发者的新宠。不同于传统的UIKit,SwiftUI通过声明式语法和强大的功能组合,为创建动态且响应式的用户界面提供了一种更加简洁高效的方式。本文将深入探讨如何利用SwiftUI技术构建具有高度自定义能力和响应性的用户界面,并展示其在现代iOS应用开发中的优势和潜力。
|
1月前
|
iOS开发
iOS自动混淆测试处理笔记
iOS自动混淆测试处理笔记
12 0
|
1月前
|
开发者 iOS开发
iOS App上架新规解析:如何进行App备案
iOS App上架新规解析:如何进行App备案
144 0
|
1月前
|
iOS开发 开发者
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
|
1月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
145 2