簡體   English   中英

在Swift中,可以使用字符串來訪問struct屬性嗎?

[英]In Swift, can one use a string to access a struct property?

我有一個結構,我想知道是否可以使用括號語法訪問變量。 這是我的結構:

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中有什么方法可以做到這一點?

我認為這樣的基於字符串的訪問不是很好的Swift風格。 vadian顯示了如何做到的,但是要像這樣動態獲取和設置成員,最好使用內置的keypath功能

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而不是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
            }
        }
    }
}

var pxl = Pixel(value: 0xFEEDFACE, red: 0xFE, green: 0xED, blue: 0xFA, alpha: 0xCE)
let redChannel = pxl[.red]
print(redChannel)
pxl[.green] = 0xB5
print(pxl)

除非您使用下標(如vadian所述),否則您所描述的不是Swift功能。 如果您需要自動提供下標的內容,請使用字典。 否則,如果您確實想要真正的自省,請使用Cocoa-使用從NSObject派生的類而不是結構,並使用鍵值編碼。

只是為了娛樂並表明它是可能的,但是它很丑

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

如果OP正在尋找更清潔的替代方案,則可以使用一個吊艙將KVC擴展到本機Swift結構:

https://github.com/bradhilton/SwiftKVC

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM