100 Days of SwiftUI - Day 25 项目1
1.学到了什么
前面我们做了2个SwiftUI项目,还有一个技术性项目。我们学到了一些重要的概念:视图,修饰符,状态,堆栈布局。
我们做了这些:
1.构建一个将文本与控件混合的滚动表单,使用Picker
的基于表格的布局,或新的页面选择。
2.NavigationView
push一个新的View,提供导航栏了标题。
3.使用@State
存储要改变的数据,因为SwiftUI都是structs,所以需要使用它。
4.使用$variable
来绑定用户界面控件。
5.使用ForEach
循环创建大量视图。
6.使用VStack
, HStack
,ZStack
构建复杂布局。
7.将Color或渐变用作视图,并可以控制他们的大小。
8.使用buton。
9.定义条件,并改变它们的状态来控制弹出alert。
10.SwiftUI怎么使用some View
。
11.使用三元运算符,创建条件修饰符,来使程序展示不同的结果。
12.创建视图和自定义视图修饰符,分解代码,使我们构建更复杂的程序。
SwiftUI中,Color.red,LinearGradient,VStack,Group,ForEach
全部都是View。所有符合View协议的东西,都可以返回给body。
View协议是SwiftUI的核心。
在其它框架中,通常用类才实现,这意味着,如果继承自UIView,你将获得200多种不需要的属性和方法,以及大量的其它功能。
而在SwiftUI中,只需要在body添加一个符合View协议的东西,SwiftUI就知道如何布局。这就是面向协议编程的重要的原因。
像Text , Image, Color, Spacer。我们构建的UI在这些上面创建。
2.关键点
结构体与类
五个区别
1.类不带有成员初始化器,结构体默认有。
2.类可以使用继承来构建功能,而结构体不能。
3.复制一个类时,副本指向相同的数据。而结构体的副本是唯一的。
4.类具有反初始化器,结构体没有。
5.常量类中可以更改变量属性。常量结构体内部的属性是固定的,无论是变量或常量。
在Objective-C中,几乎所有类型都用到了类。
而在Swift中,我们可以选择class 或 struct,但是不少人在使用时,确不考虑选择class或struct的后果。
使用结构体还是类取决于你所解决的问题。重点是,当有人读取你的代码时,你的意图清晰了吗。
例如你大多数使用结构体,那么特定的地方切换到类时,可以传达一些意图:这件事与众不同,需要以不同的方式对待。
而在SwiftUI中,UI使用结构体,数据使用类。
ForEach
ForEach(0 ..< 100) { number in
Text("Row \(number)")
}
ForEach是一个视图。它允许我们绕过添加十个子视图的限制。
let agents = ["Cyril", "Lana", "Pam", "Sterling"]
VStack {
ForEach(0 ..< agents.count) {
Text(self.agents[$0])
}
}
前面我们这样写,
在循环时,Swift会确定每个项目是唯一的。
但ForEach提供了第二种方式,我们可以在数组上循环。然后直接使用。
VStack {
ForEach(agents, id: \.self) {
Text($0)
}
}
绑定
当使用如Picker或其他控件时,我可以将其双向绑定到 @State的属性,简单的属性非常有用,有时(很少)你还需要更高级的功能,使用自定义绑定来运行一些逻辑。
struct ContentView: View {
@State var selection = 0
var body: some View {
let binding = Binding(
get: { self.selection },
set: { self.selection = $0 }
)
return VStack {
Picker("Select a number", selection: binding) {
ForEach(0 ..< 3) {
Text("Item \($0)")
}
}.pickerStyle(SegmentedPickerStyle())
}
}
}
使用自定义绑定,实现一个按钮控制其它三个。
自定义绑定效果图
struct ContentView: View {
@State var agreedToTerms = false
@State var agreedToPrivacyPolicy = false
@State var agreedToEmails = false
var body: some View {
let agreeToAll = Binding (
get: {
agreedToTerms && agreedToPrivacyPolicy && agreedToEmails
},
set: {
agreedToTerms = $0
agreedToPrivacyPolicy = $0
agreedToEmails = $0
}
)
VStack {
Toggle(isOn: $agreedToTerms) {
Text("Agree to Terms")
}
Toggle(isOn: $agreedToPrivacyPolicy) {
Text("Agree to PrivacyPolicy")
}
Toggle(isOn: $agreedToEmails) {
Text("Agree to Emails")
}
Toggle(isOn: agreeToAll) {
Text("Agree to All")
}
}
}
}
自定义绑定并不常用,但了解背后的操作非常重要。
3.挑战项目
挑战是制作一款大脑训练游戏,石头,纸,剪刀上的游戏
大致来说:
游戏每回合,应用程序都会随机选择石头,纸或剪刀。
该应用程序每次旋转都会提示玩家获胜或失败。
然后,玩家必须轻按正确的招式来赢得或输掉游戏。
如果他们是正确的,他们得分。否则他们会失去一点。
游戏在10个问题之后结束,此时将显示其得分。