Let's say I have the following struct
in Swift
:
struct Data {
let old: Double
let new: Double
}
Now I have a class with an array of Data structs:
class MyClass {
var myDataArray: [Data]
}
Now let's say I want to calculate the average of either the old or the new values:
func calculateAverage(oldOrNew: String) -> Double {
var total = 0.0
count = 0
for data in myDataArray {
total += data.oldOrNew
count++
}
return total / Double(count)
}
And then:
let oldAverage = calculateAverage("old")
let newAverage = calculateAverage("new")
But this obviously doesn't work, since oldOrNew
is not a member of my struct
.
How can I access old
or new
from "old"
or "new"
?
What about this "reflection-less" solution?
struct Data {
let old: Double
let new: Double
func valueByPropertyName(name:String) -> Double {
switch name {
case "old": return old
case "new": return new
default: fatalError("Wrong property name")
}
}
}
Now you can do this
let data = Data(old: 0, new: 1)
data.valueByPropertyName("old") // 0
data.valueByPropertyName("new") // 1
You're looking for key-value-coding (KVC) that is accessing properties by key (path).
Short answer: A struct
does not support KVC.
If the struct
is not mandatory in your design use a subclass of NSObject
there you get KVC and even operators like @avg
for free.
class MyData : NSObject {
@objc let old, new: Double
init(old:Double, new:Double) {
self.old = old
self.new = new
}
}
let myDataArray : NSArray = [MyData(old: 1, new: 3), MyData(old:5, new: 9), MyData(old: 12, new: 66)]
let averageOld = myDataArray.value(forKeyPath:"@avg.old")
let averageNew = myDataArray.value(forKeyPath: "@avg.new")
Edit: In Swift 4 a struct
does support Swift KVC but the operator @avg
is not available
You wouldn't access a struct property by name in Swift any more than you would in C++. You'd provide a block.
Extemporaneous:
func calculateAverage(getter: (Data) -> Double) {
... total += getter(data) ...
}
...
calculateAverage({$0.old})
calculateAverage({$0.new})
Possibly with average {$0.old}
being a more natural syntax — the verb isn't really helpful and if you're asserting what it is, not what the computer should do, then omitting the brackets looks fine.