Josiah Agosto Josiah Agosto - 3 months ago 6
Swift Question

Why am I getting the error of "Instance Member cannot be used on type GameViewController"?

The title is one question and the other question pertaining to that one is how do i connect the class that i created to the UILabel?
Can anyone please help me. If your wondering what im doing its making a Text-Adventure Game in SpriteKit. I dont know if i should of made it in spritekit or a single view application.

Here's my Code:

import UIKit
import SpriteKit

class GameViewController: UIViewController {

@IBOutlet weak var locationName: UILabel! // Name of the Location of the game
@IBOutlet weak var userInputArrows: UILabel! // Arrows for user input
@IBOutlet weak var objectiveName: UILabel! // Name of the objective of the game
@IBOutlet weak var computerOutput: UILabel! // The AI's output or return text
@IBOutlet weak var userInputText: UITextField! // Humans input text

class Thing {
var location: String
var name: String
var computerDescription: String
init(location: String, name: String, computerDescription: String) {
self.location = location
self.name = name
self.computerDescription = computerDescription

let location = locationName.text
}
}
// Main Location is Abandoned Power Plant
// Start Location: Inside a dim lit room

let roomAbandonedPowerPlant = Thing(location: "Room", name: "ROOM", computerDescription: "A small dimly lit room " +
"with large heavy machinery. With almost complete silence.")

let machineryAbandonedPowerPlant = Thing(location: "Room", name: "MACHINERY", computerDescription: "Old corroded " +
"machines, looks like it hasn't been used in a long time.")

let paperAbandonedPowerPlant = Thing(location: "Room", name: "PAPER", computerDescription: "All crumbled up with " +
"dirt covering everything, and the lettering fading away.")

let writingAbandonedPowerPlant = Thing(location: "Room", name: "Paper WRITING", computerDescription: "The paper says: " +
"The only way out of this room is to use your imagination.")

let machineryLetteringPowerPlant = Thing(location: "Room", name: "MACHINE LETTERING", computerDescription: "It says:" +
"Built - 1890, Occupation - Used for spare oil, Made By - John Mac")

let firstKeychainPowerPlant = Thing(location: "Room", name: "KEYCHAIN", computerDescription: "Slightly shining in the dim" +
" sunlight.")

let keychainPowerPlant = Thing(location: "Room", name: "VIEW KEYCHAIN", computerDescription: "It say's: Owner: John Mac")


class Room: Thing {
}
let room = Room(location: "Room", name: "Room", computerDescription: "A small dimly lit room with large heavy " +
"machinery. With almost complete silence.")

class Machinery: Thing {
}
let machinery = Machinery(location: "Room", name: "Machinery", computerDescription: "Old corroded machines, looks " +
"like it hasn't been used in a long time.")

class Paper: Thing {
}
let paper = Paper(location: "Room", name: "Paper", computerDescription: "All crumbled up with dirt covering " +
"everything, and the lettering fading away.")

class PaperWriting: Thing {
}
let paperwriting = PaperWriting(location: "Room", name: "Paper Writing", computerDescription: "The Paper says: " +
"The only way out of this room is to use your imagination.")

class MachineLettering: Thing {
}
let machinelettering = MachineLettering(location: "Room", name: "Machine Lettering", computerDescription: "It says: " +
"Built - 1890, Occupation - Used fir spare oil, Made By - John Mac")

class Keychain: Thing {
}
let keychain = Keychain(location: "Room", name: "Keychain", computerDescription: "Slightly shining in the dim sunlight.")

class ViewKeychain: Thing {
}
let viewkeychain = ViewKeychain(location: "Room", name: "View Keychain", computerDescription: "It says: Owner: John " +
"Mac")

override func viewDidLoad() {
super.viewDidLoad()

}


}

Answer

You are receiving that error because in swift every class receives its own name space and locationName is not defined in Thing. Your larger problem is one of encapsulation. While it is possible to have nested classes like this it is uncommon. Rather classes or objects should be discrete entities having their own properties and methods that operate on those properties.

I would move Thing and its subclasses outside of GameViewController. For example:

class Thing {
    var location: String
    var name: String
    var computerDescription: String

    init(location: String, name: String, computerDescription: String)
    {
        self.location = location
        self.name = name
        self.computerDescription = computerDescription
    }
}

class Machinery: Thing {
}

class Paper: Thing {
}

class PaperWriting: Thing {
}

class MachineLettering: Thing {
}

class Keychain: Thing {
}

class ViewKeychain: Thing {
}

class Room: Thing {}

class GameViewController: UIViewController
{

    @IBOutlet weak var locationName: UILabel! // Name of the Location of the game
    @IBOutlet weak var userInputArrows: UILabel! // Arrows for user input
    @IBOutlet weak var objectiveName: UILabel! // Name of the objective of the game
    @IBOutlet weak var computerOutput: UILabel! // The AI's output or return text
    @IBOutlet weak var userInputText: UITextField! // Humans input text

    // Main Location is Abandoned Power Plant
    // Start Location: Inside a dim lit room

    let roomAbandonedPowerPlant = Thing(location: "Room", name: "ROOM", computerDescription: "A small dimly lit room " +
        "with large heavy machinery. With almost complete silence.")

    let machineryAbandonedPowerPlant = Thing(location: "Room", name: "MACHINERY", computerDescription: "Old corroded " +
        "machines, looks like it hasn't been used in a long time.")

    let paperAbandonedPowerPlant = Thing(location: "Room", name: "PAPER", computerDescription: "All crumbled up with " +
        "dirt covering everything, and the lettering fading away.")

    let writingAbandonedPowerPlant = Thing(location: "Room", name: "Paper WRITING", computerDescription: "The paper says: " +
        "The only way out of this room is to use your imagination.")

    let machineryLetteringPowerPlant = Thing(location: "Room", name: "MACHINE LETTERING", computerDescription: "It says:" +
        "Built - 1890, Occupation - Used for spare oil, Made By - John Mac")

    let firstKeychainPowerPlant = Thing(location: "Room", name: "KEYCHAIN", computerDescription: "Slightly shining in the dim" +
        " sunlight.")

    let keychainPowerPlant = Thing(location: "Room", name: "VIEW KEYCHAIN", computerDescription: "It say's: Owner: John Mac")

    let room = Room(location: "Room", name: "Room", computerDescription: "A small dimly lit room with large heavy " +
        "machinery. With almost complete silence.")

    let machinery = Machinery(location: "Room", name: "Machinery", computerDescription: "Old corroded machines, looks " +
        "like it hasn't been used in a long time.")

    let paper = Paper(location: "Room", name: "Paper", computerDescription: "All crumbled up with dirt covering " +
        "everything, and the lettering fading away.")


    let paperwriting = PaperWriting(location: "Room", name: "Paper Writing", computerDescription: "The Paper says: " +
        "The only way out of this room is to use your imagination.")

    let machinelettering = MachineLettering(location: "Room", name: "Machine Lettering", computerDescription: "It says: " +
        "Built - 1890, Occupation - Used fir spare oil, Made By - John Mac")

    let keychain = Keychain(location: "Room", name: "Keychain", computerDescription: "Slightly shining in the dim sunlight.")

    let viewkeychain = ViewKeychain(location: "Room", name: "View Keychain", computerDescription: "It says: Owner: John " +
        "Mac")

    var currentThing: Thing?
    {
        didSet
        {
            self.locationName.text = self.currentThing?.location
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.currentThing = self.paper

    }

}

Also, it's not clear if Thing's subclasses are just stubs that will get more implementation later, but if they are simple renaming of Thing you should use typealias typealias Room = Thing rather than class Room: Thing {}.

I'm confused by what you mean by connect the class to the UILabel. But you can implement a property observer that will update the label every time a property is set for example:

var currentThing: Thing?
{
    didSet
    {
        self.locationName.text = self.currentThing?.location
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.currentThing = self.paper

}

Here, a property currentThing is declared as an optional Thing. Every time currentThing is set locationName's text is set the currentThing's location. currentThing is set to paper so locationName should read "Room."

You're only using UIKit so far so a SpriteKit application does not make sense. An application based on the single view application template would make more sense.

Comments