目标:任务列表展示,任务添加
1. Xcode新建项目TodoList,选择Tabbed App, User Interface 选择swiftUI。
2. swiftUI实现list add界面
Xcode 自动生成两个Tab页面,ContentView.swift preview 窗口
ContentView Preview
First 改为list页面, Second 改为add页面
List Add 界面
@State private var todoStr = ""
@State private var descStr=""
TextField text参数需要Binding<String>类型,使用$符号将String类型转换为Binding<String>类型,关于 @State,@Binding 请参考 https://www.jianshu.com/p/527db4ae79de
3. 数据管理类TodoManager
import SwiftUI
import Combine
class TodoManager: NSObject, ObservableObject {
@Published var todos = [todo]()
func addTask(name: String, desc: String) {
todos.append(todo(name: name, desc: desc))
}
}
struct todo: Identifiable {
var id: UUID = UUID()
var name: String
var desc: String
}
实现Combine协议ObservableObject, 作为被观察者。添加一个数组变量todos, 添加Combine关键字 @Published
@Published 官方解释
/// Properties annotated with `@Published` contain both the stored value and a publisher which sends any new values after the property value has been sent. New subscribers will receive the current value of the property first.
/// Note that the `@Published` property is class-constrained. Use it with properties of classes, not with non-class types like structures.
这样todos数组有任何变化,都能及时通知订阅者。
SwiftUI的ForEach使用Identifiable来确保数组改变的时,准确定位要插入的元素,或者删除的元素。所以让struct todo实现协议Identifiable并提供id生成方法。
4. 数据显示
ContentView.swift 中 添加
@EnvironmentObject private var todoManager: TodoManager
@EnvironmentObject 会在环境中自动查找一个 TodoManager 实例,并且把找到的结果放进 todoManager 属性。所以在ContentView_Previews 及 SceneDelegate 中需要添加这个实例,否则会报错。
ContentView().environmentObject(TodoManager())
Add页面
实现Add页面按钮事件,点击Add按钮,更新todoMangaer并切换到List页面
self.todoManager.addTask(name: self.todoStr, desc: self.descStr)
self.selection = 0
List 页面
替换原来的假数据
ForEach(todoManager.todos) { todo in
VStack {
Text(todo.name)
.font(.title)
Text(todo.desc)
.font(.subheadline)
}
}
Over~
源码 https://github.com/garyZlot/TodoList
网友评论