Протоколно-ориентированное расширение модуля init дважды

Здесь ситуация. У меня есть протокол и его расширение.

protocol CustomViewAddable {
    var aView: UIView { get }
    var bView: UIView { get }
    func setupCustomView()
}
extension CustomViewAddable where Self: UIViewController {
    var aView: UIView {
        let _aView = UIView()
        _aView.frame = self.view.bounds
        _aView.backgroundColor = .grey
        // this is for me to observe how many times this aView init. 
        print("aView: \(_aView)")
        return _aView
    }
    var bView: UIView {
        let _bView = UIView(frame: CGRect(x: 30, y: 30, width: 30, height: 30))
        _bView.backgroundColor = .yellow
        return _bView
    }
    func setupCustomView() {
        view.addSubview(aView);
        aView.addSubview(bView);
    }
}

И я делаю ViewController для соответствия этому протоколу, а затем добавляю этот пользовательский "a View" в представление моего ViewController.

class MyVC: UIViewController, CustomViewAddable {
    override func viewDidLoad() {
        super.viewDidLoad()

        setupCustomView()
    }
}

Я запускаю это. В моем журнале консоли он печатает дважды init, и я пытался что-то сделать в моем собственном "a View", и это не удалось. (Код, который я вставил выше, я упростил, так что мне будет очень легко показать мое намерение)

Может ли кто-нибудь объяснить, почему или исправить это, что я буду очень признателен.

2 ответа

Решение

Потому что ваш var aView: UIView вычисляемая переменная, а не переменная магазина,

Поэтому каждый раз, когда вы звоните aViewсоздаст новый UIView,

Ты можешь использовать Associated Objects в NSObject вот несколько уроков:

Надеюсь, что это может помочь.

В основном в том, как вы реализовали setupCustomView Метод ничего не должен работать, потому что, как упоминалось в другом ответе, вы используете вычисляемое свойство, так что это означает, что каждый раз, когда вы обращаетесь к свойству, оно создается снова.

Вам не нужно использовать связанные объекты или что-то в этом роде для достижения того, чего вы хотите, вам нужно только сохранить ссылку на aView в начале, избегая повторного вызова, таким образом:

func setupCustomView() {
   let tView = aView // only is computed once
   view.addSubview(tView)
   tView.addSubview(bView)
}

Я надеюсь, что это поможет вам.

Другие вопросы по тегам