Alex Daro Alex Daro - 4 months ago 14
Swift Question

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

I have a struct and I would like to know if I can access variables using bracket syntax. Here is my 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?
}


I would like to access the variable like so
pixel["red"]
, as opposed to
pixel.red


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


Is there any way to do this in Swift?

Answer

I'm not sure string-based access like this is good Swift style. vadian shows how it can be done, but if you really need to dynamically get and set members like this, it would be best to use an enum to define the keys:

enum PixelComponent {
    case Red
    case Green
    case Blue
    case Alpha
}

Then adapt the subscript function that vadian demonstrated to accept PixelComponent instead of String.

This has a significant advantage in that you can no longer pass an invalid key.

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

    public enum PixelComponent
    {
        case Red, Blue, Green, Alpha
    }

    subscript(key: PixelComponent) -> 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)