随着复杂性的增加,犯错的几率也随之增加,Swift在这里是相当不容忍的-就像你现在无疑会看到的那样,即使第20行出现一个小错误也可能导致第5行出现随机错误,这可能是令人沮丧。

好吧,希望今天的报价对你有所启发。我之所以今天特别选择它,是因为最好留给读者阅读,但就是这样:不要惊慌!这些类型的问题很常见,现在解决这些问题的最简单方法是注释掉你最近添加的任何代码,并继续这样做,直到你的代码起作用为止。然后,你可以缓慢地重新引入代码,直到找到导致编译中断的部分,然后对其进行修复。

挑战

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

  • 将启动日期添加到MissionView任务徽章下方的。
  • 修改AstronautView以显示这位宇航员执行的所有任务。
  • 在ContentView其中显示一个栏按钮,以在显示发射日期和显示机组人员名称之间切换。

第一个挑战应该是微不足道的,第二个挑战应该是棘手的,最后一个挑战……好吧,我们只能说它将推动你。如果花费的时间比你想象的要长得多,请不要感到惊讶!

我的代码

ContentView.swift

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
import SwiftUI

struct ContentView: View {
let astronauts: [Astronaut] = Bundle.main.decode("astronauts.json")
let mission: [Mission] = Bundle.main.decode("missions.json")
@State private var showCrew = false

var body: some View {
NavigationView {
List(mission) { item in
NavigationLink(destination: MissionView(mission: item, astronauts: self.astronauts)) {
Image(item.image)
.resizable()
.scaledToFill()
.frame(width: 40, height: 40)

VStack(alignment: .leading) {
Text(item.displayName)
.font(.headline)
Text(self.showCrew ? self.membersList(mission: item) : item.formattedLaunchDate)
}
.padding(.leading)

}
}
.navigationBarTitle("Moonshot")
.navigationBarItems(trailing: Button(action: {self.showCrew.toggle()}) {
Image(systemName: self.showCrew ? "person.fill" : "timer")
})
}
}

func membersList(mission: Mission) -> String{
var members = ""

for crew in mission.crew {
members += "\(crew.name) "
}

return members
}
}

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

MissionView.swift

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 MissionView: View {
let mission: Mission

struct CrewMember {
let role: String
let astronaut: Astronaut
}

let astronauts: [CrewMember]

var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack {
Image(self.mission.image)
.resizable()
.scaledToFit()
.frame(maxWidth: geo.size.width * 0.7)
.padding(.top)
.padding(.bottom)

Text(self.mission.formattedLaunchDate)

Text(self.mission.description)
.padding()

Spacer(minLength: 25)


ForEach(self.astronauts, id: \.role){ astMember in
NavigationLink(destination: AstronautView(astronaut: astMember.astronaut)) {
HStack {
Image(astMember.astronaut.id)
.resizable()
.scaledToFit()
.frame(width: 83, height: 60)
.clipShape(RoundedRectangle(cornerRadius: 8))
.padding(.leading)

VStack(alignment: .leading) {
Text(astMember.astronaut.name)
.font(.headline)
.padding(.bottom, 6)

Text(astMember.astronaut.id)
.font(.footnote)
.foregroundColor(.gray)
}

Spacer()
}
}.buttonStyle(PlainButtonStyle())
}
}
}
.navigationBarTitle(Text(self.mission.displayName), displayMode: .inline)
}

}

init(mission: Mission, astronauts: [Astronaut]) {
self.mission = mission

var matches = [CrewMember]()

for member in mission.crew {
if let match = astronauts.first(where: { $0.id == member.name}){
matches.append(CrewMember(role: member.role, astronaut: match))
}
}

self.astronauts = matches
}
}


struct MissionView_Previews: PreviewProvider {
static let missions: [Mission] = Bundle.main.decode("missions.json")
static let astronauts: [Astronaut] = Bundle.main.decode("astronauts.json")

static var previews: some View {
MissionView(mission: missions[0], astronauts: astronauts)
}
}

AstronautView.swift

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
import SwiftUI

struct AstronautView: View {
let astronaut: Astronaut
let missions: [Mission] = Bundle.main.decode("missions.json")

let missionList: [String]

var body: some View {
GeometryReader { geo in
ScrollView(.vertical) {
VStack {
Image(self.astronaut.id)
.resizable()
.scaledToFill()
.frame(height: geo.size.width)
.frame(maxWidth: geo.size.width)


HStack {
Text(self.astronaut.name)
.font(.largeTitle)
.bold()
.padding(.leading)

Spacer()
}
.frame(maxWidth: geo.size.width)

Text(self.astronaut.description)
.padding()
.frame(maxWidth: .infinity)

Spacer(minLength: 20)

HStack {
Text("Space program")
.font(.largeTitle)
.bold()
.padding(.leading)

Spacer()
}
.frame(maxWidth: geo.size.width)
.padding(.bottom)

ForEach(self.missionList, id: \.self){ item in
HStack {
Text(item)
.font(.title)
.bold()
.padding(.leading)

Spacer()
}
.frame(maxWidth: geo.size.width)
}
}
}
}
.navigationBarTitle(Text("\(astronaut.id)"), displayMode: .inline)
}
init(astronaut: Astronaut) {
self.astronaut = astronaut

var matches = [String]()

for mission in self.missions {
if mission.crew.first(where: { $0.name == astronaut.id}) != nil{
matches.append(mission.displayName)
}
}

self.missionList = matches

}
}

struct AstronautView_Previews: PreviewProvider {
static let astronauts: [Astronaut] = Bundle.main.decode("astronauts.json")

static var previews: some View {
AstronautView(astronaut: astronauts[0])
}
}

参考资料

查看下一天的SwiftUI学习笔记

关于100days英文课程