Применить оболочку свойства в собственности суперкласса - PullRequest
0 голосов
/ 22 апреля 2020

Я создал свою собственную оболочку свойств для создания тем компонентов UI, таких как UIView, UILabel et c.

 class MyUIViewController: UIViewController {
    @Theme private override var view: UIView! // it doesnt work!!!
    @Theme private var myCustomView: UIView! // it works!!
 }

, в этом случае я получу ошибку компиляции "Невозможно переопределить с сохраненным свойство 'view' "

Я знаю, что представление является собственностью UIViewController. Знаете ли вы, есть ли какой-нибудь возможный способ применить оболочку свойства к сохраненному (суперклассу) свойству? любые предложения будут оценены :) спасибо большое!

1 Ответ

0 голосов
/ 22 апреля 2020

Я нашел способ сделать это, но это больше похоже на взлом , чем на хорошую реализацию (поэтому я бы не рекомендовал его), и я не полностью его протестировал (как это действительно на UIViewController) посмотреть механизм загрузки, это может привести к некоторому неопределенному поведению).

Тем не менее, в документации оболочки свойств вы можете найти «пример перевода», который объясняет, как работает оболочка свойств.

@Lazy var foo = 1738

// translates to:

private var _foo: Lazy<Int> = Lazy<Int>(wrappedValue: 1738)
var foo: Int {
  get { return _foo.wrappedValue }
  set { _foo.wrappedValue = newValue }
}

Таким образом, мы можем имитировать это, чтобы вручную обернуть свойство суперкласса.

Обратите внимание, что выполнение этого свойства view является немного особенным, так как представление не загружается во время инициализации контроллера представления, а больше похоже на ленивое var.

@propertyWrapper
struct Theme<WrappedValue: UIView> {
    var wrappedValue: WrappedValue?
}

class Controller: UIViewController {
    override func loadView() {
        super.loadView()
        _view.wrappedValue = view
    }

    private var _view: Theme<UIView> = .init()
    override var view: UIView! {
        get {
            if _view.wrappedValue == nil {
                // This is a trick I would not recommend using, but basically this line
                // forces the UIViewController to load its view and trigger the
                // loadView() method.
                _ = super.view
            }
            return _view.wrappedValue
        }
        set {
            _view.wrappedValue = newValue
        }
    }
}

Я сделал обернутое значение в оболочке свойства необязательным, поскольку свойство view равно nil во время процесса инициализации (поскольку представление еще не загружено)

...