尽量记住美国作家和讲师Dale Carnegie的一些著名话:

“不要害怕尽力去做看似小的工作。每次征服一个职位,都会使自己变得强大—如果你的小工作做得好,那么大的工作往往会照顾自己。”

在函数中使用guard来检查是否满足一定条件否则退出

在函数中可以使用guard来检查,例如:

1
2
3
guard answer.count > 0 else {
return
}

将单词全部小写并删除空格和换行符

1
let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)

输入框按下return执行函数

1
TextField("Enter your word", text: $newWord, onCommit: addNewWord)

在数组头部插入内容

我们有的时候需要将内容插入到数组的第一个元素中:

1
usedWords.insert(answer, at: 0)

禁用输入框第一个字母大写

1
.autocapitalization(.none)

SFsymbol图标:圆圈数字

我们将使用Apple的SF Symbols图标来显示文本旁边每个单词的长度。SF Symbols提供从0到50的圆圈数字,所有数字均使用“ x.circle.fill”格式命名-因此1.circle.fill,20.circle.fill。

1
2
3
4
List(usedWords, id: \.self) {
Image(systemName: "\($0.count).circle")
Text($0)
}

让程序报错

Swift为我们提供了一个名为的函数fatalError(),该函数可以使我们真正清楚地发现问题。当我们调用fatalError()它时-无条件且总是-导致我们的应用程序崩溃。它会死。不是“可能死”或“可能死”:它总是会立即终止。

我意识到这听起来很糟糕,但是它让我们做的事情很重要:对于像这样的问题,例如,如果我们忘记在项目中包含文件,那么试图使我们的应用程序处于崩溃状态就没有任何意义。最好立即终止并给我们清楚的说明出了什么问题的原因,以便我们可以纠正问题,而事实正是fatalError()如此。

1
fatalError("Could not load start.txt form bundle.")

在显示视图时运行闭包

SwiftUI为我们提供了一个专用的视图修饰符,用于在显示视图时运行闭包,因此我们可以使用它来调用startGame()并使事物移动–在以下位置添加此修饰符navigationBarTitle():

1
.onAppear(perform: startGame)

查看数组是否包含该元素

我们已经有了一个usedWords数组,因此我们可以将单词传递给它的contains()方法并将结果发送回如下

1
2
3
func isOriginal(word: String) -> Bool {
!usedWords.contains(word)
}

也可以使用firstIndex:

1
2
3
4
5
6
7
8
9
10
11
12
13
func isPossible(word: String) -> Bool {
var tempWord = rootWord

for letter in word {
if let pos = tempWord.firstIndex(of: letter) {
tempWord.remove(at: pos)
} else {
return false
}
}

return true
}

代码

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import SwiftUI

struct ContentView: View {
@State private var usedWords = [String]()
@State private var rootWord = ""
@State private var newWord = ""

@State private var errorTitle = ""
@State private var errorMessage = ""
@State private var showingError = false

var body: some View {
NavigationView {
VStack {
TextField("Enter your word", text: $newWord, onCommit: addNewWord)
.autocapitalization(.none)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
List(usedWords, id: \.self){
Image(systemName: "\($0.count).circle")
Text($0)
}
}
.navigationBarTitle(rootWord)
.onAppear(perform: startGame)
}.alert(isPresented: $showingError){
Alert(---
title: Text(errorTitle), message: Text(errorMessage), dismissButton: .default(Text("OK")))
}

}
func addNewWord() {
//将单词全部小写并删除空格和换行符
let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
guard isOriginal(word: answer) else {
wordError(---
title: "word used already", message: "Be more original")
return
}
guard isPossible(word: answer) else {
wordError(---
title: "Word not recongnized", message: "You can't just make them up, you know!")
return
}
guard isReal(word: answer) else {
wordError(---
title: "Word not possible", message: "That isn't a real word.")
return
}
//判断是否有字符,没有则退出
guard answer.count > 0 else {
return
}

//将输入的文本加入到数组
usedWords.insert(answer, at: 0)
newWord = ""
}

func startGame(){
// 获取资源库中的文件
if let startWordsURL = Bundle.main.url(forResource: "start", withExtension: "txt"){
// 将文件中的内容加入字符串
if let startWords = try? String(contentsOf: startWordsURL){
// 通过换行符将字符串分割为数组
let allWords = startWords.components(separatedBy: "\n")
rootWord = allWords.randomElement() ?? "sillkworm"
// 执行到这里就可以返回了
return
}
}
//如果产生问题则报错
fatalError("Could not load start.txt form bundle.")
}

func isOriginal(word: String) -> Bool {
!usedWords.contains(word)
}

func isPossible(word: String) -> Bool {
var tempWord = rootWord

for letter in word {
if let pos = tempWord.firstIndex(of: letter) {
tempWord.remove(at: pos)
}else {
return false
}

}
return true
}

func isReal(word: String) -> Bool {
let checker = UITextChecker()
let range = NSRange(location: 0, length: word.utf16.count)
let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")

return misspelledRange.location == NSNotFound
}

func wordError(---
title: String, message: String) {
errorTitle = title
errorMessage = message
showingError = true
}
}

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

参考资料

查看下一天的SwiftUI学习笔记

关于100days英文课程