余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

SwiftUI入门 - TodoLists数据的本地持久化(vuex数据持久化存储)

xiyangw 2022-12-03 12:00 18 浏览 0 评论

置顶

菜鸟入门,各位大佬轻喷,如有谬误之处欢迎讨论建议,也欢迎各位道友与我同行

“不积跬步,无以至千里;不积小流,无以成江海”

继续

上文中我们解实现 todo 的详情表单,即在 List 中点击每一项弹出一个 todo 的表单,里面可以修改 todo 的名称等。

但是发现有一个问题,即每次退出程序时,我们已有的 todo 项全部被重置,再次打开又成了默认的那一条。

所以,本文我们将来实现普通数据的本地持久化保存,包括存储与取消存储。效果如下:

思考

之前我们用过 @AppStorage 来进行持久化存储,但是 @AppStorage 只支持几个基础的数据类型,我们构造的 TodoLists 显然不是个基础类型。

@AppStorage 确实挺好用的,我们拿它来进行初始化或者保存数据是可以的,既然它只支持基础类型,那么我们将 TodoListsJSONEncoder 转化成 String,进行存取应是可行的。

那么基本的实现方案即修改 TodoModel 添加一个 saveData 方法和 clearData 方法,并修改 TodoModelinit 方法 ,优先使用 @AppStorage 中的数据

实现

修改 TodoModel.swfit

import SwiftUI;
// 一定要添加 Encodable 和 Decodable
struct TodoItem:Identifiable,Equatable,Encodable,Decodable{
    // 把 let 改成var,现在需要id可以被修改了
    var id = UUID();
    var name:String ;
    var isFinished:Bool = false;
    var createTime:Int = 0;
    var finishTime:Int = 0;
    var createdAt:String {
        // ...
    }
}

class TodoLists : ObservableObject { 
    // 添加 @AppStorage 参数
    @AppStorage("todoLists") public var store:String = "";
    @Published private(set) var todoList:[TodoItem];
    init(todoList: [TodoItem]) {
        self.todoList = todoList
        // 如果是个空数组,那么先放一个进去
        if(todoList.count == 0 ){
            // 使用 @AppStorage 里面的数据来进行初始化
            if(store == ""){
                // 本身就没有值的时候新增一条默认的
                add(name: "请添加TODO")
            }else{
                // 这里在将 @AppStorage 中的值进行解码,然后放到 todoList 变量上去
                guard (try? self.todoList = JSONDecoder().decode([TodoItem].self, from: store.data(using: .utf8)!)) != nil else{
                    return;
                }
            }
        }
    }
    // 添加一条 todo项,只要名称即可
    func add(name:String){
        // ...
        saveData()
    }
    // 切换todo项的是否完成状态,如果完成状态为true那更新finishTime
    func toggle(item:TodoItem){
        // ...
        saveData()
    }
    // 删除todo
    func delete(offsets: IndexSet,isFinished:Bool = false){
        // ...
        saveData()
    }
    // 更新数据
    func update(item:TodoItem){
        // ...
        saveData()
    }
    // 将数据保存到 @AppStorage
    func saveData(){
        // 将 todoList JSON化后存入 store变量中,利用 @AppStorage 进行存储
        guard let data = try? JSONEncoder().encode(self.todoList) else{
            return;
        }
        store = String(data:data, encoding: .utf8)!;
    }
    // 清除所有的todo项
    func clear(){
        todoList = [];
        saveData();
    }
}

既然已经有了清除所有数据的方法,那么我们就可以在 Setting 页面中添加一个按钮,用于清除所有的 todo 项,同时显示已有多少条

先将 IndexView 中的 EnvironmentObject 挂到最外层,保证 Setting 能够取得到这个全局实例。

//  IndexView.swift
import SwiftUI
struct IndexView: View{
    // ...
    let todos = TodoLists(todoList: [])
    
    var body: some View{
        // ...
        VStack{
            // 一个简单的tabview,底部导航栏
            TabView {
                TodoView()
                    .tabItem {
                        Image(systemName: "list.dash")
                        Text("TODO")
                    }.tag(0)
                SettingView()
                    .tabItem {
                        Image(systemName: "gear.circle")
                        Text("设置")
                    }.tag(1)
            }
            .font(.headline)
        }.environmentObject(todos)
    }
}

修改 Setting.swift 如下:

//  SettingView.swift
import SwiftUI
struct SettingView: View {
    @AppStorage("isLogin") private var isLogin:Bool = false;
    @AppStorage("userName") private var userName:String = "";
    // 从 EnvironmentObject 中 拿出 todos
    @EnvironmentObject var todos:TodoLists;
    var body:some View{
        NavigationView{
            if(isLogin){
                List{
                    // ...
                    Section{
                        HStack{
                            Spacer()
                            Text("清除所有的Todo,共\(todos.todoList.count)条").foregroundColor(.red)
                            Spacer()
                        }.onTapGesture {
                            todos.clear()
                        }
                    }
                    Section{
                        HStack{
                            Spacer()
                            Text("退出登陆").foregroundColor(.red)
                            Spacer()
                        }.onTapGesture {
                            isLogin = false;
                            // 退出登陆时也应当清楚 todos
                            todos.clear()
                        }
                    }
                }.navigationTitle("设置")
            }else{
                Text("请登录").foregroundColor(.red)
            }
        }
    }
}

总结

  1. @AppStorage 的存储时机不确定,可能存在丢失的可能,以后再研究,目前仅实现功能。
  2. @AppStorage 是保存和读取 UserDefaults 变量的一种快捷方式,即本身就是 UserDefaults。但只支持几种基础数据类型,其它的需要自己扩展
  3. SwiftUI 里的 try 有三种方式: try? 会在出错时,返回 nil,不会导致程序崩溃,如果没有错误,会返回一个可选值,try! 会在出错时崩溃,打破错误传播链,当然还有 do...catch
  4. JSONDecoderJSONEncoder 的基本使用

相关推荐

前端入门——JavaScript 操作符(前端常用js)

所谓操作符,就是用来操作数据值的符号,在JavaScript中包括算术操作符、位操作符、关系操作符和相等操作符。这些操作符可以操作所有类型的数据,比如字符串、数字、布尔值,甚至对象。一元操作符所谓一元...

带你入门JS的世界,首先需要建立正确的心智模型(一)
带你入门JS的世界,首先需要建立正确的心智模型(一)

转载说明:原创不易,未经授权,谢绝任何形式的转载开篇当我们编写代码时,我们倾向于使用“快速思考系统”,这是一种基于模式匹配和直觉的思考方式。然而,这种思考方式往...

2023-03-21 18:26 xiyangw

10分钟入门javascript函数式编程(什么是函数式编程)

1.函数式编程1.什么是函数式编程函数式编程是?种编程范式,强调使?函数来组合和处理数据。将运算过程抽象成成函数,可以复?。常?的编程范式有:?向过程编程(ProceduralProgrammin...

JavaScript 初学者手册(javascript零基础入门)
JavaScript 初学者手册(javascript零基础入门)

JavaScript是世界上最流行的编程语言之一。我相信这是您第一个绝佳选择的编程语言。我们主要使用JavaScript来创建:网站网络应用使用Node.j...

2023-03-21 18:25 xiyangw

JavaScript零基础入门—JavaScript的BOM(javascript基础入门教程)
JavaScript零基础入门—JavaScript的BOM(javascript基础入门教程)

其实,我们日常开发中,如果不是做前端架构,一般情况下,对BOM的操作其实并不会太多,当然,H5的话也可以借助BOM来定位和判断网络,这个以后再说。对于BOM的操...

2023-03-21 18:25 xiyangw

前端入门——JavaScript 函数(前端function函数的用法)

函数概念说到函数我们首先会想到数学中的函数公式,但是在编程中函数的概念和你想象中的可能有所不同。所谓函数就是一段可以被其它程序引用的代码或程序,可以叫它子程序。函数的作用就是将一个大的系统程序按功能分...

「JavaScript 教程」入门篇-导论(javascript技术教程)

1、什么是JavaScript语言?JavaScript是一种轻量级的脚本语言。所谓“脚本语言”(scriptlanguage),指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应...

如何快速掌握Javascript入门小知识(造价入门需掌握的知识)

如果你想要学一门语言,那就应该选择Javascript,为什么会这么说呢?因为当前推出的许多新技术都支持这个观点,Javascript作为一种直译式脚本语言,早是在HTML网页上使用,用来给HTML网...

「JavaScript 教程」入门篇-JavaScript 的基本语法

1、语句JavaScript程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是一个语句。语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句。...

Javaweb开发必备,JavaScript技术详解,JS从入门到精通

JavaScript编程语言:1.专门在浏览器编译与执行的编程语言2.帮助浏览器解决用户提出简单需求3.基于面向对象采用弱类型语法风格实现JavaScript学习教程老杜讲解的JavaScript教程...

小白入门篇|前辈多年经验放送:如何学好Javascript
小白入门篇|前辈多年经验放送:如何学好Javascript

首先要说明一下,我不是大神,算是入了JS的门,顶多是半桶水,在这里给大家分享一下我学习js的一些教训。这个时候有人要说,“你丫半桶水,凭啥教我们”。但是大家忘了...

2023-03-21 18:24 xiyangw

前端入门——JavaScript 介绍(前端js基础知识)

JavaScript最早诞生于1995年,当时主要用来处理输入验证操作,随着时间的发展它成为了市面上浏览器必备的一项功能。如今JavaScript不仅仅局限于简单的数据校验,它已经具备与浏览器窗口及...

初学者轻松学习 JavaScript 的路线图(javascript学习指南)
初学者轻松学习 JavaScript 的路线图(javascript学习指南)

JavaScript是一种多功能且功能强大的编程语言,可用于前端和后端Web开发。无论你是一个完全的初学者还是已经有一些编程经验,这里有一个路线图可以帮助...

2023-03-21 18:23 xiyangw

前端入门——JavaScript 语句(前端js基础知识点)

在编程语言中语句通常使用一个或多个关键字来完成特定的任务。比如定义变量、赋值、条件判断、循环等语句。下面我们将介绍JavaScript中大部分常用的语句,主要分以下几类:声明和赋值语句条件语句循环语句...

JavaScript入门(Javascript入门经典第七版)
JavaScript入门(Javascript入门经典第七版)

什么是JavaScriptJavaScript是一门函数优先的轻量级、解释型的编程语言。运行的环境需要浏览器的支持。JavaScript是在1995年由...

2023-03-21 18:23 xiyangw

取消回复欢迎 发表评论: