执行环境
- macOS Mojave: 10.14.5
- xcode: Version 11.0 beta 6 (11M392q)
项目信息
github: https://github.com/young-cowboy/swiftui-app-habits
App 效果预览
页面结构设计
一共有 4 个页面 HabitListView, AddButtonView, HabitDetailView, AddItemView
数据结构设计
项目涉及到三个数据结构: HabitItem(习惯项), HabitIconArray(习惯图标), HabitColor(习惯主题)
HabitColor 主题色,保存了习惯的主题
public let UserColorArray = [
Color(red:75 / 255, green:166 / 255, blue: 239 / 255),
Color(red:161 / 255, green:206 / 255, blue: 97 / 255),
Color(red:248 / 255, green:214 / 255, blue: 80 / 255),
Color(red:243 / 255, green:176 / 255, blue: 74 / 255),
Color(red:238 / 255, green:140 / 255, blue: 111 / 255),
Color(red:237 / 255, green:113 / 255, blue: 165 / 255),
Color(red:207 / 255, green:102 / 255, blue: 247 / 255),
Color(red:77 / 255, green:110 / 255, blue: 247 / 255),
Color(red:236 / 255, green:107 / 255, blue: 102 / 255)
]
HabitIconArray 习惯的图标库
public let IconNameArray: [String] = [
"alarm",
"book",
"pencil",
"desktopcomputer",
"gamecontroller",
"sportscourt",
"lightbulb"
]
HabitItem 用来保存习惯的详细信息,这里实现 ObservableObject 协议,用来告诉 SwiftUI 这个对象需要监听,用 Published property wrapper 包装了 checkList 属性,表示这个属性是要监听的,因为它可能需要传递给子 View
class HabitItem: Identifiable, ObservableObject {
var name: String = ""
var iconName: String = "clock"
var theme: Color = UserColor.color1.value
var uuid: Int = 0
@Published var checkList: [Bool] = [false, false, false, false, false, false, false]
init () {
}
init(name: String, iconName: String, theme: Color) {
self.name = name
self.iconName = iconName
self.theme = theme
self.uuid = generatteID()
}
}
UI 设置
具体代码参考仓库代码,这里讲解一个流程,新建一个“习惯”项,在 MainView 里
MainView
...
@State var sheetVisible: Bool = false
@State var sheetType: String = "add"
...
...
AddButtonView() {
self.sheetType = "add"
self.sheetVisible = true
}
...
AddButtonView 利用尾部闭包语法
内联了一个闭包用来相应事件
AddButtonView
里定义了 onPressed 属性
struct AddButtonView: View {
var onPressed: () -> Void
var body: some View {
Button(action: {
self.onPressed()
}) {
HStack {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 60, height: 60)
.foregroundColor(Color.blue)
}
}
}
}
AddItemView
里的新增按钮点击后相应事件,把选中的数据传递 onSumit 属性回调里
struct AddItemView: View {
@State var newItemTitle = ""
@State var selectIconIndex: Int = 0
@State var selectColorIndex: Int = 0
var onSumit: (HabitItem) -> Void
var onDissmis: () -> Void
var body: some View {
VStack {
...
...
VStack {
Button(action: {
if self.newItemTitle != "" {
let iconName = IconNameArray[self.selectIconIndex];
let theme = UserColorArray[self.selectColorIndex];
self.onSumit(HabitItem(name: self.newItemTitle, iconName: iconName, theme: theme))
}
}) {
Text("新增").frame(minWidth: 0, maxWidth: .infinity)
}
...
}
...
}
...
}
}
}
在 MainView 里,利用闭包处理回调事件新增选项
AddItemView(onSumit: { item in
self.habitItemList.insert(item, at: 0)
self.sheetVisible = false
}, onDissmis: { self.sheetVisible = false })
剩下的功能大同小异,可以把代码拉下来本地运行看看效果
谢谢