具有静态间距的UIStackView子类

时间:2018-09-05 15:01:41

标签: ios swift uikit subclass

我正在创建UIStackView的子类,并且我希望间距是静态的并且不可重写。我认为可以通过覆盖spacing属性来简单地做到这一点:

class MyStackView: UIStackView {
    override var spacing: CGFloat {
        get { return 8.0 }
        set {}
    }
}

但是,这不起作用。永远不会调用该吸气剂,也不显示任何间距。我为此找到的唯一解决方案是以下代码:

class MyStackView: UIStackView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        super.spacing = 8.0
    }

    override var spacing: CGFloat {
        get { return 8.0 }
        set {}
    }
}

实际上,我在get中返回的内容并不重要,无论如何都不会调用它。

有人可以解释这个行为吗?如何避免?

1 个答案:

答案 0 :(得分:1)

在我看来,这是怎么回事。您想实现两件事:

  1. 默认情况下,MyStackView处的间距应为8.0
  2. 该间距值不能从外部更改

要实现第一件事,您需要覆盖初始化器并在其中设置默认值。

class MyStackView: UIStackView {

    private let defaultSpacing: CGFloat = 8.0

    override init(frame: CGRect) {
        super.init(frame: frame)
        super.spacing = defaultSpacing
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        super.spacing = defaultSpacing
    }

}

第二件事,您需要覆盖getter的{​​{1}}和setter,以控制外部的任何变化。

spacing

为什么不能简单地覆盖变量并获得相同的结果?

class MyStackView: UIStackView { ... override var spacing: CGFloat { get { return defaultSpacing } set { print("MyStackView spacing it always \(defaultSpacing)") } } } 属性是计算得出的,它不是容器。我们可能不在乎原始UIStackView.spacing的工作原理,因为我们知道间距始终是相同的。我们知道它的值,并且总是可以在重写的getter处返回它。

但是我们也不知道原始getter的工作原理以及它在setter中所做的更改。从那以后,我们不能简单地覆盖UIStackView。我们必须显式调用一次getter,以触发原始的super.spacing = defaultValue并设置所需的值。