面向协议的编程扩展变量init两次

时间:2017-01-13 03:01:52

标签: swift swift-protocols protocol-extension protocol-oriented

情况如下。我有一个协议,并扩展它。

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以符合此协议,然后我添加了这个自定义' aView'到我的ViewController的视图。

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

        setupCustomView()
    }
}

我跑了。在我的控制台日志中,它打印了两次init,我尝试在我的自定义' aView'它失败了。 (我在上面粘贴的代码,我简化了以便它很容易显示我的意图)

任何人都可以解释为什么或解决它,我会非常感激。

2 个答案:

答案 0 :(得分:1)

因为你的var aView: UIView是计算变量而不是存储变量,

因此,每次拨打aView时,都会创建一个新的UIView

您可以在Associated Objects中使用NSObject这里有一些教程:

希望这可能会有所帮助。

答案 1 :(得分:1)

基本上在你实现setupCustomView方法的方式中,什么都不应该有效,因为正如在另一个响应中提到的那样,你正在使用一个计算属性,所以这意味着每次你访问该属性时它都会再次创建。

您不需要使用关联对象或类似的东西来实现您想要的东西,您只需要在开头时保留aView的引用,避免调用它再次,这样:

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

我希望这对你有所帮助。