在Swift中,可以使用字符串来访问struct属性吗?

时间:2016-07-09 19:10:13

标签: swift struct

我有一个结构,我想知道我是否可以使用括号语法访问变量。这是我的结构:

import UIKit

public struct Pixel {
    public var value: UInt32
    public var red: UInt8
    public var green: UInt8
    public var blue: UInt8
    public var alpha: UInt8
}

public struct RGBAImage {
    public var pixels: [ImageProcessor_Sources.Pixel]
    public var width: Int
    public var height: Int
    public init?(image: UIImage)
    public func toUIImage() -> UIImage?
}

我想访问变量pixel["red"],而不是pixel.red

var image = RGBAImage(image: image!)!
var pixel = image.pixels[index]
pixel["red"] = 255 // as opposed to pixel.red

有没有办法在Swift中这样做?

4 个答案:

答案 0 :(得分:5)

我不认为像这样的基于字符串的访问是很好的Swift风格。 vadian shows如何做到这一点,但要像这样动态获取和设置成员,最好使用the built-in keypath functionality

let redChannel = pixel[keyPath: \.red]
pixel[keyPath: \.green] = 0xB5

另一个选项(在Swift 4之前更相关)是使用枚举来定义键:

enum Component
{
    case red
    case green
    case blue
    case alpha
}

然后调整vadian演示接受subscript而不是Pixel.Component的{​​{1}}函数。

这具有明显的优势,因为您无法再传递无效密钥。

根据您的定义:

String
public extension Pixel
{
    public enum Component
    {
        case red, blue, green, alpha
    }

    public subscript(key: Component) -> UInt8
    {
        get
        {
            switch key {
                case .red: return self.red
                case .green: return self.green
                case .blue: return self.blue
                case .alpha: return self.alpha
            }
        }
        set
        {
            switch key {
                case .red: self.red = newValue
                case .green: self.green = newValue
                case .blue: self.blue = newValue
                case .alpha: self.alpha = newValue
            }
        }
    }
}

答案 1 :(得分:3)

您所描述的不是Swift功能,除非您使用下标(如vadian所解释的)。如果您想要自动提供下载的内容,请使用字典。否则,如果你真的想要真正的内省,使用Cocoa - 使用从NSObject派生的类而不是结构,并使用键值编码。

答案 2 :(得分:1)

只是为了好玩并表明它是可能的,但它很难看

public struct Pixel {
  public var value: UInt32
  public var red: UInt8
  public var green: UInt8
  public var blue: UInt8
  public var alpha: UInt8

  subscript(key: String) -> UInt8 {
    get {
      switch key {
      case "red": return self.red
      case "green": return self.green
      case "blue": return self.blue
      case "alpha": return self.alpha
      default: fatalError("Invalid key")
      }
    }
    set {
      switch key {
      case "red": self.red = newValue
      case "green": self.green = newValue
      case "blue": self.blue = newValue
      case "alpha": self.alpha = newValue
      default: fatalError("Invalid key")
      }
    }
  }
}

答案 3 :(得分:0)

如果OP正在寻找更清洁的替代方案,那么有一个将KVC扩展到本机Swift结构的pod:

https://github.com/bradhilton/SwiftKVC