Hazar Panc
Hazar Panc

Reputation: 35

Referring to an object using a string variable's value in Swift

In my code below, I can't get performActivity method to increase character happiness. Because 'need' comes as a string with the value "happiness" whereas I need to make changes on "happiness" which is a class instance. I'd appreciate any help!

// Character Needs Class
class CharNeeds {
    var currentNeedValue : Int = 0

    func changeNeedValue (changeBy : Int){
        currentNeedValue += changeBy
    }


}

// Activities Class

class Activities{
    let activityName : String
    var effects = [String: Int]()

    //Initializers
    init(activityName: String, effects: [String: Int]){
        self.activityName = "Unnamed Activity"
        self.effects = effects
    }

    //Methods
    static func performActivity(activityName : Activities){

        for (need, effect) in activityName.effects {
            need.changeNeedValue(changeBy: effect)
        }
    }
}

//Testing

var happiness = CharNeeds()
var cycling = Activities(activityName: "cycling", effects: ["happiness":10])
Activities.performActivity(activityName: cycling)

Upvotes: 0

Views: 49

Answers (1)

Rob Napier
Rob Napier

Reputation: 299275

This design is backwards in a few ways. Make each need an object, and have each activity modify it directly. There's no need (or desire) for strings here. It's also a bit easier to work with this if you store the effects as a DictionaryLiteral rather than a Dictionary. That way we don't need to go through the trouble of making needs Hashable.

// A need has an immutable name and a mutable value that can be increased and read
class Need {
    let name: String
    private(set) var value = 0

    init(name: String) {
        self.name = name
    }

    func increaseValue(by: Int){
        value += by
    }
}

// An Activity has an immutable name and an immutable list of needs and adjustments
class Activity {
    let name: String
    let effects: DictionaryLiteral<Need, Int>

    init(name: String, effects: DictionaryLiteral<Need, Int>){
        self.name = name
        self.effects = effects
    }

    func perform() {
        for (need, effect) in effects {
            need.increaseValue(by: effect)
        }
    }
}

// Now we can assign happiness to this activity, and perform it.
let happiness = Need(name: "happiness")
let cycling = Activity(name: "cycling", effects: [happiness: 10])
cycling.perform()
happiness.value

If you receive strings, then you just need to keep a mapping of strings to Needs. For example:

let needMap = ["happiness": Need(name: "happiness")]
if let happiness = needMap["happiness"] {
    let cycling = Activity(name: "cycling", effects: [happiness: 10])
    cycling.perform()
    happiness.value
}

Upvotes: 2

Related Questions