这篇文章介绍了如何使用SwiftUI创建一个单词游戏应用程序,包括使用guard检查条件、将单词全部小写并删除空格和换行符、禁用输入框第一个字母大写、在数组头部插入内容等技术。此外,还介绍了如何使用SF Symbols图标来显示文本旁边每个单词的长度,并介绍了Swift中的fatalError()函数,用于使应用程序崩溃并清楚地说明出现的问题。
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结
投诉尽量记住美国作家和讲师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英文课程