`Reflection` property wrapper, do I need it?

I have my own UI classes but want to hide inner implementation via private access level. But I still need some properties for configuration like text, placeholder which will be just referencing the inner implementation. But in this case, I have to write a lot of duplicated code {set{...} get{...}} which do the same things and if I'll have more such properties the number lines of code will grow fast.

class MyTextField: UIView {
  @IBOutlet private var innerTextField: UItextField!
  var placeholder: String? { 
    set {
      innerTextField.placeholder = newValue
    }
    get {
      return innerTextField.placeholder
    }
  }

  var text: String? { 
    set {
      innerTextField.text = newValue
    }
    get {
      return innerTextField.text
    }
  }
}

So I've created a Reflection property wrapper to reduce number of lines and code duplication(the same template).

@propertyWrapper
public struct Reflection<Value, Object: AnyObject> {
  private let keyPath: ReferenceWritableKeyPath<Object, Value>
  private var innerValue: Value
  private weak var _sourceObject: Object? {
    didSet {
      _sourceObject?[keyPath: keyPath] = innerValue
    }
  }

  public var sourceObject: Object? {
    set {
      if newValue == nil {
        assertionFailure("`sourceObject` should be set up")
      }
      _sourceObject = newValue
    }
    get {
      if _sourceObject == nil {
        assertionFailure("`sourceObject` should be set up")
      }
      return _sourceObject
    }
  }

  public init(
    wrappedValue initialValue: Value,
    keyPath: ReferenceWritableKeyPath<Object, Value>
  ) {
    self.keyPath = keyPath
    self.innerValue = initialValue
  }

  public var wrappedValue: Value {
    get {
      return sourceObject?[keyPath: keyPath] ?? innerValue
    }
    set {
      innerValue = newValue
      sourceObject?[keyPath: keyPath] = innerValue
    }
  }
}

So right now implementation looks like:

class MyTextField: UIView {
  @IBOutlet private var innerTextField: UItextField!

  @Reflection(keyPath: \UITextField.placeholder)
  var placeholder: String? = nil
 
  @Reflection(keyPath: \UITextField.text)
  var text: String? = nil
  
  init() {
    _text.sourceObject = textField
    _placeholder.sourceObject = textField
  }
}

So my question is it possible somehow remove lines in init method? Or may be general question does it really make sence to have such property wrappers? because probably doing _text.sourceObject = textField is a quite big downside of this solution.

Terms of Service

Privacy Policy

Cookie Policy