干货swift实现todo状态切换
置顶
菜鸟入门,各位大佬轻喷,如有谬误之处欢迎讨论建议,也欢迎各位道友与我同行
"不积跬步,无以至千里;不积小流,无以成江海"
继续
上文中已经实现了 TODO 页面的基本新增逻辑以及删除功能
本文将实现数据每一个 TODO 项的完成状态切换、创建时间
以及滑动删除功能。
同时完成一个数据的抽象,即将数据处理的部分抽象到一个对象内,页面中只管调用即可。
最终效果如下:
思考
还是老规矩,既然要抽象一个数据模型出来,那就是一个独立的文件。
一个关于 TODO 的数据模型。
至少有两个 struct ,一个 todoItem 的定义,另一个是 todoList 的定义
这个数据模型中是所有的关于这个 todo lists 的操作
如果所有的操作都集中在这个模型中,那我我们的 todo 页面中的所有操作即可调用这个数据模型。 实现
我们新增一个 TodoModel.swift ,内容如下: import SwiftUI; // 这里是定义 todo 项的数据结构,结构体用于定义结构,类用于定义完整数据对象 struct TodoItem:Identifiable,Equatable{ // 给生成一个唯一的id作为标识,相当于实现了 Identifiable let id = UUID(); // todo项名称 var name:String ; // 是否已经完成,默认为false var isFinished:Bool = false; // 创建时间 var createTime:Int = 0; // 完成时间 var finishTime:Int = 0; // 用来展示的时间,这里相当于是个 computed var createdAt:String { // 将时间戳转为时间字符串 if(createTime == 0) { return ""; } let date:Date = Date.init(timeIntervalSince1970: Double(createTime)) let formatter = DateFormatter.init() formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" return formatter.string(from: date as Date) } } // ObservableObject 代表这是一个可以被观察的对象 class TodoLists : ObservableObject { // @Published 代表这个变量的任何变化都会被发布到外面使用这个变量的地方,更新视图 // private(set) 代表这个变量的设置、修改等对外隐藏,但是对外可见 // [TodoItem] 代表这是一个数组,里面的每一条数据都是 TodoItem 类型的 @Published private(set) var todoList:[TodoItem]; init(todoList: [TodoItem]) { self.todoList = todoList // 如果是个空数组,那么先放一个进去 if(todoList.count == 0 ){ add(name: "请添加TODO") } } // 添加一条 todo项,只要名称即可 func add(name:String){ if(name == ""){ return ; } var item = TodoItem(name: name); item.createTime = Int(Date().timeIntervalSince1970); self.todoList.insert(item,at: 0); } // 切换todo项的是否完成状态,如果完成状态为true那更新finishTime func toggle(item:TodoItem){ // 找到这一条的索引 index,$0代表这个方法的第一个参数 let index = todoList.firstIndex(where: {$0.id == item.id}) if index != nil { // index! 代表我知道这个index一定存在,不用再进行判断了 todoList[index!].isFinished.toggle() // 如果是完成,那么更新已完成时间,否则改为0 if(todoList[index!].isFinished == true){ todoList[index!].finishTime = Int(Date().timeIntervalSince1970); }else{ todoList[index!].finishTime = 0; } } } // 删除todo func delete(offsets: IndexSet){ offsets.forEach { index in todoList.remove(at: index) } } }
既然我们数据模型已经定义好了,那么自然要修改 TodoView.swift 页面中的使用
修改如下:
TodoView.swift import SwiftUI struct TodoView: View { // 是否已经登陆 @AppStorage("isLogin") private var isLogin:Bool = false; // 已经登陆的用户名 @AppStorage("userName") private var userName:String = ""; // 输入框输入的新的TODO @State private var newItem:String = ""; // 使用我们新的数据模型 @StateObject private var todos = TodoLists(todoList: []); var body: some View { VStack{ HStack{ TextField("请输入新的TODO",text:$newItem).onSubmit { todos.add(name: newItem) newItem = "" } Button("确认"){ todos.add(name: newItem) newItem = "" } }.padding() List{ // Foreach 开始循环 TodoLists 的indices,需要它的索引值,用于删除等 // id 需要为一个 Identifier,可以预见,之后我们自己构造数据类型的时候也需要一个 Identifier ForEach(todos.todoList){ item in HStack{ VStack{ HStack{ // 字符串拼接,之前已有使用 Text("(item.name)") Spacer() } HStack{ Text("(item.createdAt)").font(.subheadline) Spacer() } }.foregroundColor(item.isFinished ? .gray : .primary) // 这里用个Group套起来,里面用三元实现点击切换图标,展示是否已经完成 Group{ item.isFinished ? Image(systemName: "circle.fill") : Image(systemName: "circle") } }.contentShape(Rectangle()) .onTapGesture { todos.toggle(item: item) } // 这个调用将实现横滑删除功能 }.onDelete{ IndexSet in todos.delete(offsets: IndexSet) } }.animation(.default,value:todos.todoList) } } } struct TodoView_Previews: PreviewProvider { static var previews: some View { TodoView() } }总结1. ObservableObject 与 @Published 是在主动定义一个可观察的对象,虽然可以添加许多操作,但是感觉上反而不如 reactive 方法更简洁2. 目前看来, Struct 一般用来定义结构或者视图,Class 才是我们普遍意义上的类。3. 数据抽象虽然简化了View,但是感觉比较繁琐,或许我应该考虑直接都放到 Struct View 里面去,参考 Vue 的结构进行编排,各有优劣,后头试试4. 横滑删除的功能非常好实现,直接在 Foreach 后加上 .onDelete 即可5. SwiftUI 中有很多这种加方法调用即可实现视图以及功能的方法,也许可以参考到 Vue 或者其他的前端封装里面6. 想实现一个 computed 变量,直接 var 一个,然后在底下写方法即可
人民日报每日金句摘抄1。如果你不花时间,去创造你想要的生活,你将被迫花很多时间,去应付你所不想要的生活,成功的路上,没有人会叫你起床,也没有人会为你买单,你需要自我管理,自我约束,自我突破。2。时间流
湖北枣阳大黑马白手起家,29岁办公司,已年入836588万元湖北省,是我国中部地区的经济大省,经济体量在全国排名位居前十,主要经济产业较为发达,加上经济结构常年不断优化,所以,该省综合经济实力较强,尤其在中部地区属于数一数二的经济强省,人均
中国经济正在向好继11月上旬的第一轮人民币资产保卫战大获全胜之后,第二轮反击在近日又展开了!最亮眼的标志是,人民币对美元的离岸价,在昨夜今晨逼近了7。02。虽然截至12月1日,人民币对美元的离岸价
苹果10月国内市场份额达25,网友华为Mate50系列也挡不住?最近市场调研机构Counterpoint的月度销量数据显示,2022年10月苹果手机的销量环比增长了21,市场份额达到了25,达到了历史最高水平,也就是说每卖出4部手机,里面就有1
恭喜詹姆斯!湖人更新出战名单,佩林卡对杜兰特感兴趣北京时间12月1日,NBA常规赛已经开启第六十二天左右,其中追梦格林表示,兰姆首次训练就用投篮征服了我,他这个赛季的表现一直发挥出色,东契奇透露,裁判吹这么多走步让我有点惊讶,很高
加纳VS乌拉圭韩国VS葡萄牙加纳VS乌拉圭加纳有利情报加纳自1963年起,参加过23次非洲杯,4次拿到过该项赛事的冠军。加纳参加了2006年世界杯,在2010年南非世界杯上,他们成为第三支进入世界杯八强的非洲
阿根廷出线,外媒更新夺冠概率荷兰5,葡萄牙8,一队高达25过去的一天时间,世界杯又进行了4场小组赛,赛果分别是澳大利亚10丹麦,突尼斯10法国,沙特12墨西哥,波兰02阿根廷。C组和D组的排名也就全部诞生了,阿根廷顺利拿到6分,成为C组头
高血压患者这种思想不能有今天接诊一位高血压患者,与其短短几分钟的对话,发人深思。该患者自诉高血压病史已经20多年了,最高血压180110mmHg,但平时没有任何症状。我问他您平时吃什么药啊?患者回答我吃的
5年阴囊潮湿,内裤湿异味重,调理2个多月,解决男人的困扰阴囊潮湿,是男性常见的问题,我之前门诊上就有很多这样的患者。前阵子在门诊上遇到周先生,他才38岁,有阴囊潮湿已经5年了,一开始就只是感觉下面湿漉漉的,有时候内裤都湿了,很难受。从中
梅西传从侏儒症患者到世界球王,13岁打远走他乡打生长激素你一定会成为这个世界上最好的球员,梅西的外婆摸着年仅6岁的梅西的头说道,梅西对此深信不疑。那一天,外婆的话在他瘦弱矮小的身体里发芽长大。十岁那年,一直激励梅西前进的外婆不幸去世。祸
口臭,大便溏泄,小便黄,肢体困倦,脾胃湿热该怎么办?脾胃是我们人体十分重要的器官,能帮我们运化水谷,转化为我们人体所需要的能量,一旦脾胃出了问题,就容易产生很多疾病,比较常见的就是由于脾胃湿热带来的大便溏泄,小便黄,乏力,口臭,厌食