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 v
I don't think string-based access like this is good Swift style. vadian shows how it can be done, but to dynamically get and set members like this, it would be best to use the built-in keypath functionality:
let redChannel = pixel[keyPath: \.red]
pixel[keyPath: \.green] = 0xB5
Another option (more relevant prior to Swift 4) would be to use an enum to define the keys:
enum Component
{
case red
case green
case blue
case alpha
}
Then adapt the subscript
function that vadian demonstrated to accept Pixel.Component
instead of String
.
This has a significant advantage in that you can no longer pass an invalid key.
Based on your definition:
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)
Just for fun and to show that it is possible, but it's ugly
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")
}
}
}
}
What you're describing is not a Swift feature, unless you use subscripting (as vadian has explained). If you want something that supplies subscripting automatically, use a dictionary. Otherwise, if you really want true introspection, use Cocoa — use a class derived from NSObject instead of a struct, and employ key-value coding.
If OP is looking for a cleaner alternative, there is a pod that extends KVC to native Swift structs:
https://github.com/bradhilton/SwiftKVC