0

I have an internal dictionary that I don't want to expose to the user. Instead, I expose only certain values using properties, like this:

public var artist: String? {
  get {
     return items["artist"]
  }
  set {
     items["artist"] = newValue
  }
}

//...so on for another 20 or so items

As you can imagine, this ends up getting repeated quite a lot. I was thinking that property wrappers would be a nice way to clean this up - however, it's not possible to pass items directly to the wrapper, since property wrappers are created before init (so self would not be accessible).

Is there a way around this, or is this just one of the limitations of propertyWrappers?

Tobi Schweiger
  • 111
  • 1
  • 6

1 Answers1

1

You could build a generic solution. I did one, but you can probably improve it:

    class PropertyWrapper {
    
    private var items: [String: Any] = ["artist": "some dude"]
    
    enum Key: String {
        case artist
    }
    
    func getItem<T: Any>(key: Key) -> T {
        guard let item = items[key.rawValue] as? T else {
            preconditionFailure("wrong type asked for")
        }
        return item
    }
    
    func setItem(value: Any, key: Key) {
        items[key.rawValue] = value
    }
}

class GetValueClass {
    
    func getValue() {
        let wrapper = PropertyWrapper()
        let value: String = wrapper.getItem(key: .artist)
    }
}

class SetValueClass {
    
    func setValue() {
        let wrapper = PropertyWrapper()
        wrapper.setItem(value: "some", key: .artist)
    }
}
Vollan
  • 1,887
  • 11
  • 26
  • Thanks! I have tried the static approach (failed to mention that), and it's a bit problematic, because I can have multiple instances of the class that contains the properties (i.e. multiple `Foos` each with their own `artist`, `album`, etc), and those values in the items dictionary would all be shared (which may not be desirable). – Tobi Schweiger Aug 10 '20 at 18:49
  • 1
    Wait, that means you have a reference to the class object, hence you don't need static? you can just do `propertyWrapper.getValue()` instead of `PropertyWrapper.getValue()` – Vollan Aug 10 '20 at 19:05
  • Is there a particular reason you're not using the @propertyWrapper annotation? But I think you're right about the static. However, I believe there is one more issue that we may need to account for. We can now nicely wrap our dictionary items, but when we set an item, it only gets updated in the dictionary that's part of the propertyWrapper, not of `foo` itself, making our updates basically useless since they are not reflected in the "parent dict" (if that makes sense). – Tobi Schweiger Aug 10 '20 at 19:24