在 Swift 中通过名称作为字符串访问结构体属性

问题描述 投票:0回答:3

假设我在

struct
中有以下
Swift

struct Data {
   let old: Double
   let new: Double
}

现在我有一个带有数据结构数组的类:

class MyClass {
   var myDataArray: [Data]
}

现在假设我想计算旧值或新值的平均值:

func calculateAverage(oldOrNew: String) -> Double {
   var total = 0.0
   count = 0

   for data in myDataArray {
      total += data.oldOrNew
      count++
   }

   return total / Double(count)
}

然后:

let oldAverage = calculateAverage("old")
let newAverage = calculateAverage("new")

但这显然行不通,因为

oldOrNew
不是我的
struct
的成员。

如何从

old
new
访问
"old"
"new"

swift struct
3个回答
8
投票

这个“无反射”解决方案怎么样?

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")
        }
    }
}

现在你可以这样做

let data = Data(old: 0, new: 1)

data.valueByPropertyName("old") // 0
data.valueByPropertyName("new") // 1

7
投票

您正在寻找通过键(路径)访问属性的键值编码(KVC)。

简短回答:A

struct
不支持KVC。

如果

struct
在您的设计中不是强制性的,请使用
NSObject
的子类,您可以免费获得 KVC 甚至像
@avg
这样的运算符。

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")

编辑:在 Swift 4 中,

struct
确实支持 Swift KVC,但运算符
@avg
不可用


0
投票

在 Swift 中你不会像在 C++ 中那样通过名称访问结构体属性。你会提供一个块。

即兴:

func calculateAverage(getter: (Data) -> Double) {
    ... total += getter(data) ...
}

...

calculateAverage({$0.old})
calculateAverage({$0.new})

可能

average {$0.old}
是一种更自然的语法 - 这个动词并没有真正的帮助,如果你断言它是什么,而不是计算机应该做什么,那么省略括号看起来不错。

© www.soinside.com 2019 - 2024. All rights reserved.