【问题标题】:Swift: Interpolation of Property Names?Swift:属性名称的插值?
【发布时间】:2016-01-28 18:38:53
【问题描述】:

在 Swift 中是否可以从其他属性的内容中插入属性(变量)名称?在下面的代码段中,在第一个 for 循环中,我想将属性 eachItem 设置为包含在旋转数组中的项目名称。然后在第二个内部 for 循环中,我想遍历由 eachItem 属性中的内容命名的数组。

var groupA = ["groupA1", "groupA2", "groupA3"]
var groupB = ["groupB1", "groupB2", "groupB3", "groupB4", "groupB5", "groupB6"]
var groupC = ["groupC1", "groupC2", "groupC3", "groupC4", "groupC5"]

var rotation = ["groupA", "groupB", "groupC"]

for eachGroup in rotation {
  for eachItem in \(eachGroup) {
    print(eachItem)
  }
}

通过两个 for 循环的迭代将给我们:

eachGroup = "groupA"
  eachItem = "groupA1"
  eachItem = "groupA2"
  eachItem = "groupA3"
eachGroup = "groupB"
  eachItem = "groupB1"
  eachItem = "groupB2"
  eachItem = "groupB3"
  eachItem = "groupB4"
  eachItem = "groupB5"
  eachItem = "groupB6"
eachGroup = "groupC"
  eachItem = "groupC1"
  eachItem = "groupC2"
  eachItem = "groupC3"
  eachItem = "groupC4"
  eachItem = "groupC5"

在 Swift 中是否可以进行变量/属性名称插值?如果是这样,我该怎么做?

另外,使用二维数组来处理这个问题会更好吗?如果是这样,我该怎么做?

【问题讨论】:

    标签: arrays swift interpolation variable-names


    【解决方案1】:

    您可能需要字典而不是数组。为什么不这样做:

    var rotation = [groupA, groupB, groupC]

    您也可以在这样的数组数组上使用 flatMap。

    【讨论】:

    • 数组数组!我没有想到这一点,它应该很好用
    【解决方案2】:

    使用二维字符串数组,嵌套 for .. in 循环与您的示例相同:

    var groupA : [String] = ["groupA1", "groupA2", "groupA3"]
    var groupB : [String] = ["groupB1", "groupB2", "groupB3", "groupB4", "groupB5", "groupB6"]
    var groupC : [String] = ["groupC1", "groupC2", "groupC3", "groupC4", "groupC5"]
    
    var rotation : [[String]] = [groupA, groupB, groupC]
    
    for eachGroup in rotation {
        for eachItem in eachGroup {
            print(eachItem)
        }
    }
    

    为了技术讨论,您可以通过使用运行时自省和基础类NSObject 对属性名称进行插值。现在,我看不到任何人曾经真正诉诸于此,因为它以我无法...(所以不要)的方式非 Swifty,但请注意它可以 完成:

    class Container : NSObject {
        let dummyArr : [String] = []
        let groupA : [String] = ["groupA1", "groupA2", "groupA3"]
        let groupB : [String] = ["groupB1", "groupB2", "groupB3", "groupB4", "groupB5", "groupB6"]
        let groupC : [String] = ["groupC1", "groupC2", "groupC3", "groupC4", "groupC5"]
    
        init(_ rotation: [String]) {
            super.init()
    
            let a = Mirror(reflecting: self).children.filter { $0.label != nil }
            for eachGroup in a where eachGroup.label != "dummyArr" {
                print("eachGroup: \(eachGroup.label ?? "")")
                let b = self.valueForKey(eachGroup.label ?? "dummyArr")
                if let eachGroup = b as? [String] {
                    for eachElement in eachGroup {
                        print("\teachElement = \(eachElement)")
                    }
                }
            }
        }
    }
    
    var rotation = ["groupA", "groupB", "groupC"]
    let _ = Container(rotation)
    

    打印输出:

    /*  eachGroup: groupA
            eachElement = groupA1
            eachElement = groupA2
            eachElement = groupA3
        eachGroup: groupB
            eachElement = groupB1
            eachElement = groupB2
            eachElement = groupB3
            eachElement = groupB4
            eachElement = groupB5
            eachElement = groupB6
        eachGroup: groupC
            eachElement = groupC1
            eachElement = groupC2
            eachElement = groupC3
            eachElement = groupC4
            eachElement = groupC5   */
    

    【讨论】:

    • 这确实有效,尽管您不需要显式键入属性,因为类型推断在这里很有效。事实上,为了获得最佳实践,Swift 文档建议您不要显式声明属性类型,除非 Swift 无法从代码中插入类型。
    • @SillyGoof 我在此处添加了显式类型,以便(向 OP)阐明如何将字符串数组作为成员放入字符串数组的数组中,但最好指出这一点以便读者请勿将此推断为必需品,谢谢。
    • 我很欣赏这种对插值的深入研究。现在,这引出了一个问题:如果可以在 Objective-C 中进行属性名称的插值,尽管非常混乱,我想知道他们是否可以建立一个桥梁,以便我们可以用一种简单的 Swift-y 方式来做?跨度>
    • @SillyGoof 这只是我的想法,但我会假设:不。它在某种程度上规避了 Swift 著名的类型安全性:即使我们可以使用可选绑定(w.r.t. 试图访问不存在的属性)使其在某种程度上是类型安全的,但我们仍然对未定义的行为持开放态度。我个人永远不会(ab-?)在我的一些实际软件中以这种方式使用动态属性检查。但是,嘿,我们永远不知道:0)
    • 你知道,既然你提到了类型安全,我同意允许属性名称插值可能不是一个好主意。感谢您指出这一点!
    【解决方案3】:

    非常感谢你们三位的快速帮助! :)

    对于可能想知道的其他人,我的最终代码如下:

    var groupA = ["groupA1", "groupA2", "groupA3"]
    var groupB = ["groupB1", "groupB2", "groupB3", "groupB4", "groupB5", "groupB6"]
    var groupC = ["groupC1", "groupC2", "groupC3", "groupC4", "groupC4"]
    
    var rotation = [groupA, groupB, groupC]
    
    for eachGroup in rotation {
      for eachItem in eachGroup {
        print(eachItem)
      }
    }
    

    至于关于属性名称插值的原始问题,它在 Swift 中似乎是不可能的,可能(并且明智地如此)因为它们强调类型安全。

    【讨论】:

      猜你喜欢
      • 2013-01-29
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多