I would like to know if there is a way to automatically update the value in a dictionary based on changes made to values in another dictionary. I have 2 dictionaries as follows:
enum CharacterAttributes: String, Codable {
case strength
case constitution
case dexterity
case intelligence
}
enum CharacterStats: String, Codable {
case maxHealthPoint
case maxTacticPoint
case maxActionPoint
case movementSpeed
}
var attributes = [CharacterAttributes: Float]()
var stats = [CharacterStats: Float]()
The logics are:
stats[.maxHealthPoint] = attributes[.constitution] * 100
stats[.maxTacticPoint] = (attributes[.dexterity] + attributes[.intelligence]) * 1.5
stats[.maxActionPoint] = attributes[.constitution] * 10
stats[.movementSpeed] = attributes[.dexterity] + 70
What I want to achieve is that whenever a value is changed from attributes dictionary, the corresponding values in stats get updated automatically. I know for a normal variable I can use didSet keyword, but how to apply the concept to dictionaries?
Thanks in advance for any help.
Try using the didSet
observer after encapsulating your dictionaries within a class:
import Foundation
enum CharacterAttributes: String, Codable {
case strength
case constitution
case dexterity
case intelligence
}
enum CharacterStats: String, Codable {
case maxHealthPoint
case maxTacticPoint
case maxActionPoint
case movementSpeed
}
class Character {
private var _attributes = [CharacterAttributes: Float]() {
didSet {
updateStats()
}
}
private var _stats = [CharacterStats: Float]()
var attributes: [CharacterAttributes: Float] {
get { _attributes }
set {
_attributes = newValue
updateStats()
}
}
var stats: [CharacterStats: Float] {
get { _stats }
set {
_stats = newValue
}
}
init(attributes: [CharacterAttributes: Float]) {
self._attributes = attributes
updateStats()
}
private func updateStats() {
_stats[.maxHealthPoint] = (_attributes[.constitution] ?? 0) * 100
_stats[.maxTacticPoint] = ((_attributes[.dexterity] ?? 0) + (_attributes[.intelligence] ?? 0)) * 1.5
_stats[.maxActionPoint] = (_attributes[.constitution] ?? 0) * 10
if _stats[.movementSpeed] == nil { // Allow manual setting
_stats[.movementSpeed] = (_attributes[.dexterity] ?? 0) + 70
}
}
}
Example Usage:
var character = Character(attributes: [.constitution: 5, .dexterity: 3, .intelligence: 2])
print(character.stats)
character.attributes[.constitution] = 7
character.stats[.movementSpeed] = 100
character.attributes[.dexterity] = 4
print(character.stats)
Output:
[SwiftPlayground.CharacterStats.maxHealthPoint: 500.0, SwiftPlayground.CharacterStats.maxTacticPoint: 7.5, SwiftPlayground.CharacterStats.maxActionPoint: 50.0, SwiftPlayground.CharacterStats.movementSpeed: 73.0]
[SwiftPlayground.CharacterStats.maxHealthPoint: 700.0, SwiftPlayground.CharacterStats.maxTacticPoint: 9.0, SwiftPlayground.CharacterStats.maxActionPoint: 70.0, SwiftPlayground.CharacterStats.movementSpeed: 100.0]