Instance member 'formattedWord' cannot be used on type 'Game'

Hello,

Working on a Apple tutorial for swift and have the code below and keep getting the
Instance member 'formattedWord' cannot be used on type 'Game' error message.

I cannot quite figure out why the message, I understand what It is telling me, but not sure how to resolve the error.

Thanks for your help.

import UIKit

class ViewController: UIViewController {
var listOfWords = ["bad", "ace","dead", "feed","bee"]
let incorrectMovesAllowed = 7

var totalWins = 0
var totalLosses = 0
var currentGame: Game! //Ok for Game! not have a value for a short period of time.

@IBOutlet weak var treeImageView: UIImageView!

@IBOutlet weak var correctWordLabel: UILabel!

@IBOutlet weak var scoreLabel: UILabel!

@IBOutlet var letterButtons: [UIButton]!

@IBAction func buttonPressed(_ sender: UIButton) {
    sender.isEnabled = false
    let letterString = sender.title(for: .normal)!
    _ = Character(letterString.lowercased())
}

override func viewDidLoad() {
    super.viewDidLoad()
    newRound()
    updateUI()
    // Do any additional setup after loading the view, typically from a nib.
}

func newRound() {
    let newWord = listOfWords.removeFirst()
    currentGame = Game(word: newWord, incorrectMovesRemaining:incorrectMovesAllowed, guessedLetters: [])
        updateUI()
}

@IBAction func buttonTapped(_ sender: UIButton) {
    sender.isEnabled = false
    let letterString = sender.title(for: .normal)!
    let letter = Character(letterString.lowercased())
    currentGame.playerGuessed(letter: letter)
    updateUI()
}

    func updateUI() {
    correctWordLabel.text = Game.formattedWord
    scoreLabel.text = "Wins: \(totalWins), Losses: \totalLosses)"
    treeImageView.image = UIImage(named: "Tree \(currentGame.incorrectMovesRemaining)")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

formattedWord is [presumably — you didn't show that part of the code] a property in the Game class. That means you need a Game object, such as currentGame, to get the property from.

You've just written the name of the class (Game.formattedWord) instead of an object of the class. The compiler is saying you can't do that.

Some Swift terminology will help you with the error message. An object of some class is an instance of the class. For example, property currentGame is set to an instance of Game.

Properties that can have a different value for each different instance are called instance properties. (There are also class properties, which have a single value for the class as a whole, unrelated to any specific instance.)

A member of a class is a property or function in the class. An instance member, therefore, is an instance property or an instance function (aka instance method).

If you put all those pieces together, your error message says, in effect: "Only instances of class Game can provide a value for formattedWord."

Thank you and sorry for the delayed response. Here is the other part of the code below, I totally understand what you are saying but what I did looks correct based on what you said. Am I missing something?

import Foundation

struct Game {
var word: String
var incorrectMovesRemaining: Int
var guessedLetters: [Character]
var formattedWord: String {
var guessedWord = ""
for letter in word.characters {
if guessedLetters.contains(letter) {
guessedWord += "(letter)"
} else {
guessedWord += "_"
}
}
return guessedWord
}
mutating func playerGuessed(letter: Character) {
guessedLetters.append(letter)
if !word.contains(letter) {
incorrectMovesRemaining -= 1
}
}
}

Let's approach this as a brain-teaser…

Here is a simplified version of your code that you can compile in a playground:

struct Game {
    var word: String
    var formattedWord: String {
        return "_" + word + "_"
    }
}

let g1 = Game(word: "one")
let g2 = Game(word: "two")
let g3 = Game(word: "three")

print(Game.formattedWord)

Q1. If this compiled without an error, what you expect to be printed?

Now replace the last line with this:

print(g2.formattedWord)

Q2. What would you expect to be printed?

2 Likes

Q1. You would an error as g1, g2, g3 are all equal to Game.

Q2. You would return _ two _

Your answer to Q1 shows a serious misunderstanding. Neither g1, g2, nor g3 are equal to Game, they are Games. If that compiled without error (which it doesn't), I would expect it to print "(Property)" or "(Getter)", much like this prints "(Function)":

struct Foo {
    func bar() -> String {
        return "bar"
    }
}

print(Foo.bar)

Or putting that another way:

You need a particular game to ask for its formattedWord value, because all the games are different.

That's why the compiler tells you it can't compile Game.formattedWord.