如何避免快速属性观察器发生无限循环

时间:2020-05-02 15:10:16

标签: swift design-patterns

我正在尝试在某些流行的设计应用程序中实现类似于“组”层功能的逻辑。

假设我的网域中有一个班级,可以有一些孩子,并且其父级是同一类型。我希望当我更新父母的框架时,孩子们按比例调整他们的框架。同样,当孩子的镜架发生变化时,我希望对父母的镜架进行更新,从而相应地包装孩子。


class Layer {
    var parent: Layer?
    var children: [Layer]

    var frame: CGRect {
        didSet {
            if parent != nil {
                // Tell parent to update its frame
            }

            children.forEach { (child) in
                // tell the child to update it's frame
            }
        }
    }
}

当父母的镜框得到更新时,他告诉孩子们更新他们的镜框,然后孩子们回到父母那里,要求更新其镜框。而且我们陷入了无限循环。

我想知道哪种方法是实现此目标的正确方法,以及是否有解决此问题的设计模式。

谢谢。

2 个答案:

答案 0 :(得分:0)

您将无法通过属性来执行此操作。您需要一个带有参数的方法,该方法指示不更新哪个父/子层。因此,当父级更新其子级框架时,它将传递对自身的引用,以便子级不更新父级框架。而且,当孩子更新其父框架时,它将传递对自身的引用,因此父目录不会更新该孩子。

class Layer {
    var parent: Layer?
    var children: [Layer]

    private(set) var frame: CGRect

    func update(frame: CGRect) {
        update(frame: frame, sender: nil)
    }

    private func update(frame: CGRect, sender: Layer? = nil) {
        self.frame = frame

        if sender !== parent {
            parent?.update(frame: SOME_FRAME, sender: self)
        }

        children.forEach { child in
            if child !== sender {
                child.update(frame: SOME_FRAME, sender: self)
            }
        }
    }
}

答案 1 :(得分:-1)

更新组件图形的正确方法是调用layoutIfNeeded方法,因此您需要这样做

self.layoutIfNeeded();

parent.layoutIfneeded();