UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: button that calls a function: project 5

Forums > SwiftUI

Good afternoon all,

I am trying to add a left bar button that calls startGame( ), but am not having much success.

After reviewing my prior notes/code, I am able to add a button to the navigation bar, and have it print, but am having trouble when it comes to calling a function.

Under NavigationView, directly below .navigationBarTitle(rootWord) is wrote the following, where I am trying to have the code call the function startGame( )

 .navigationBarItems(leading: Button(.add, target: self, action: #selector(startGame)))

Swift doesnt like this approach, so really appreciate thoughts/advice on how to write it so that the button calls startGame(), so that a user can restart with a new word whenever they want.

full code is as follows, just so it's available for review if necessary....


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)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .autocapitalization(.none)
                    .padding()

                List(usedWords, id: \.self) {
                    Image(systemName: "\($0.count).circle")
                    Text($0)

                }
            }
            .navigationBarTitle(rootWord)

            .navigationBarItems(leading: Button(.add, target: self, action: #selector(startGame)))

            .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: "Please be more original")
            return
        }

        guard isPossible(word: answer) else {
            wordError(title: "Word not recognized", message: "You can't just make them up")
            return
        }

        guard isReal(word: answer) else {
                wordError(title: "Word not possible", message: "That isn't a real word")
            return
       }

        guard answer.count >= 3 else {
            wordError(title: "Word isn't possible", message: "It is less than 3 characters")
            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 = ""
    }

    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()
                    ?? "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.lowercased()

        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()
    }
}

2      

Use .toolbar instead of .navigationBarItems (this is depreciated in iOS14)

.toolbar {
    ToolbarItem(placement: .navigationBarLeading) {
        Button("Start Game", action: startGame)
    }
}

2      

As @NigelGee says, .navigationBarItems is deprecated starting in iOS14.

But the problem here isn't that you are using .navigationBarItems. It's this code:

Button(.add, target: self, action: #selector(startGame))

Target/action is a UIKit pattern and isn't used in SwiftUI. In SwiftUI, you would use something like this instead:

Button(action: startGame) {
    Image(systemName: "plus.square")
}

Or the example Nigel gave:

Button("Start Game", action: startGame)

2      

thanks guys!

really appreciate the help.

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.