面向协议编程扩展变量初始化两次

Protocol-Oriented Programming Extension variable init twice

情况是这样的。我有一个协议及其扩展。

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' 中做一些事情,但它失败了。 (我上面粘贴的代码我简化了,这样很容易显示我的意图)

任何人都可以解释原因或修复它,我将不胜感激。

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

所以每次你调用aView,它都会创建一个新的UIView

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

希望这可能有所帮助。

基本上,在您实现 setupCustomView 方法的方式中,应该没有任何工作,因为正如在另一个响应中提到的,您使用的是计算 属性,所以这意味着每次您访问 属性又创建了

你不需要使用associated-objects之类的东西来实现你想要的,你只需要保留[=12=的引用] 一开始避免再次调用它,这样:

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

希望对你有所帮助。