Day 29, 30, 31 of #100DaysOfSwiftUI

Start 100DaysOfSwiftUI from 2020.Mar.18th.

Day 29, 30, 31: Project 5, part one, two, three
done with 80min

New findings: followings are new findings

List
show some rows with data, looks similar to Form, but Form will ask for the input.
UITextChecker
for spell checking, but it comes from Objective-C world...
RoundedBorderTextFieldStyle
this will show rounded border for TextField
TextField trainig closure
it will be called when user press return key, it is same with onCommit
.autocapitalization
this modifier can stop "auto-capitalization" feature of textfield
OnAppear
looks simlar with viewWillAppear
fatalError
in the case no way to continue, fatalError will be the only way we can take.
struct ContentView: View {
    @State private var usedWords = [String]()
    @State private var rootWord = ""
    @State private var newWord = ""
    @State private var score = 0
    
    @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)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
                .autocapitalization(.none)
                List(usedWords, id:\.self) {
                    Image(systemName: "\($0.count).circle")
                    Text($0)
                }
                Text("Score : \(score)")
                .padding()
            }
            .navigationBarTitle(rootWord)
            .navigationBarItems(leading: Button(action: startGame ) {
                Text("Restart Game")
            })
            .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 answer.count > 0 else {
            return
        }
        
        guard isOriginal(word: answer) else {
            wordError(title: "Word used already", message: "Be more original")
            return
        }
        
        guard isPossible(word: answer) else {
            wordError(title: "Word not recognized", 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
        }
        
        usedWords.insert(answer, at: 0)
        newWord = ""
        score += (answer.count)*(answer.count)
    }
    
    func startGame() {
        usedWords = []
        score = 0
        if let startTxtUrl = Bundle.main.url(forResource: "start", withExtension: "txt") {
            if let startWords = try? String(contentsOf: startTxtUrl) {
                let allWords = startWords.components(separatedBy: "\n")
                rootWord = allWords.randomElement() ?? "silkworm"
                return
            }
        }
        fatalError("Could not load start.txt from 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 {
        if word.count < 3 { return false}
        if word == rootWord { return false }
        
        let checker = UITextChecker()
        let range = NSRange(location: 0, length: word.utf16.count)
        let missspelledRange = checker.rangeOfMisspelledWord(in: word, range: range,
                                                             startingAt: 0, wrap: false, language: "en")
        return missspelledRange.location == NSNotFound
    }
    
    func wordError(title: String, message: String) {
        errorTitle = title
        errorMessage = message
        showingError = true
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です