Protocol-Oriented Programming Extension variable init twice

151 Views Asked by At

Here is the situation. I have a protocol, and extension of it.

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);
    }
}

And I make a ViewController to conform this protocol then I add this custom 'aView' to my ViewController's view.

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

        setupCustomView()
    }
}

I run it. In my console log it prints twice of init and I trying to do something in my custom 'aView' and it failed. (The code I paste above that I simplified so that it'll be very easy to show my intension)

Could anybody to explain why or make a fix to it that I'll be very appreciated.

2

There are 2 best solutions below

0
On BEST ANSWER

Because your var aView: UIView is computed variable not store variable,

So every time you call aView, it will create a new UIView,

You can use Associated Objects in NSObject here is some tutorials:

Hope this may help.

0
On

Basically in the way you implemented the setupCustomView method nothing should work because as mentioned in another response you're using a computed property, so this implies that every time you access the property it's created again.

You don't need to use associated-objects or something like that to achieve what you want, you only need to keep the reference of the aView at the beginning avoiding calling it again, in this way:

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

I hope this help you.