挑战

最好的学习方法之一是尽可能多地编写自己的代码,因此,你应该尝试以下三种方式扩展此应用程序,以确保你完全了解正在发生的事情:

挑战1

创建一个自定义ViewModifier(和附带的View扩展名),使视图具有适合视图中显着标题的大的蓝色字体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import SwiftUI

struct ---
title: ViewModifier{
func body(content: Content) -> some View {
content
.font(.title)
.foregroundColor(.blue)

}
}

extension View {
func titleStyle() -> some View {
self.modifier(Title())
}
}


struct ContentView: View {
var body: some View {
Text("Hello, World!")
.titleStyle()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

挑战2

返回项目1-WeSplit,如果用户选择了0%提示,则使用条件修饰符将文本总数视图更改为红色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import SwiftUI



struct ContentView: View {
@State private var checkAmount = ""
@State private var numberOfPeopleString = ""
@State private var numberOfPeople = 2
@State private var tipPercentage = 2
let tipPercentages = [10, 15, 20, 25, 0]

var sumMoney: Double {

let tipSelection = Double(tipPercentages[tipPercentage])
let orderAmount = Double(checkAmount) ?? 0

let tag1 = orderAmount * tipSelection / 100
let tag2 = tag1 + orderAmount

return tag2
}

var totalPerPerson: Double {
let tag2 = sumMoney
let peopleCount = Double(numberOfPeopleString) ?? 1

let tag3 = tag2 / peopleCount

return tag3
}

var body: some View {
NavigationView {
Form {
Section {
Text("Hello World")
TextField("Amount", text: $checkAmount)
.keyboardType(.decimalPad)
}

Section (header: Text("Number of people")){
TextField("Fill in the number of people", text: $numberOfPeopleString)
.keyboardType(.numberPad)
}


Section(header: Text("How much tip do you want to leave?")) {

Picker("Tip Percentage", selection: $tipPercentage) {
ForEach(0 ..< tipPercentages.count) {
Text("\(self.tipPercentages[$0])")
}

}.pickerStyle(SegmentedPickerStyle())
}

Section(header: Text("Total amount of money")) {
Text("$\(sumMoney, specifier: "%.2f")")
.foregroundColor(tipPercentage == 4 ? .red : .black)
}

Section(header: Text("Amount per person")) {
Text("$\(totalPerPerson, specifier: "%.2f")")

}

}
.navigationBarTitle("WeSplit")
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

挑战3

返回 项目2-GuessTheFlag 并创建一个FlagImage()视图,该视图使用我们拥有的一组特定的修饰符来渲染一个标志图像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import SwiftUI

struct ImgView: ViewModifier {
func body(content: Content) -> some View {
content
.clipShape(Capsule())
.overlay(Capsule().stroke(Color.black, lineWidth: 1))
.shadow(color: .black, radius: 2)
}
}

extension View {
func flagimg() -> some View {
self.modifier(ImgView())
}
}

struct ContentView: View {
@State private var showingScore = false
@State private var scoreTitle = ""
@State private var score = 0

@State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
@State private var correctAnswer = Int.random(in: 0...2)

var body: some View {
ZStack {
LinearGradient(gradient: Gradient(colors: [.blue, .black]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all)
VStack(spacing: 30.0) {
VStack {
Text("Tap the flag of")
.foregroundColor(Color.white)

Text(countries[correctAnswer])
.font(.largeTitle)
.fontWeight(.black)
.foregroundColor(Color.white)

Text("Score: \(score)")
.foregroundColor(Color.white)
.padding(.top)

}

ForEach(0 ..< 3) { number in
Button(action: {
self.flagTapped(number)
}) {
Image(self.countries[number])
.renderingMode(.original)
.flagimg()
}
}
Spacer()

}

}.alert(isPresented: $showingScore) {
Alert(---
title: Text(scoreTitle), message: Text("Your score is \(score)"), dismissButton: .default(Text("Continue")))
}
}
func flagTapped(_ number: Int) {
if number == correctAnswer{
scoreTitle = "Correct"
self.score += 1

}else {
scoreTitle = "Wrong![]That's \(countries[number]) flag"
self.score -= 1
}

showingScore = true
}

func askQuestion(){
countries.shuffle()
correctAnswer = Int.random(in: 0...2)
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

不确定的返回类型

关键字some View是为返回类型。这使我们可以发回某种视图,而无需确切地说出哪种视图。

自定义视图

定义视图修饰符必须符合ViewModifier协议

这有一个要求:body()返回的方法some View

参考资料

查看下一天的SwiftUI学习笔记

关于100days英文课程