我正在创建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中返回的内容无关紧要,无论如何都不会调用它。

谁能解释这个行为,以及如何避免?

最佳答案

我认为这是怎么回事。您想要实现两件事:

  • 默认情况下,MyStackView的间距应为8.0
  • 间距值不能从
  • 外部更改

    要实现第一件事,您需要覆盖初始化程序并在其中设置默认值。
    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
        }
    
    }
    

    第二件事,您需要覆盖gettersetterspacing,以从外部进行任何更改。
    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,以触发原始setter并设置所需的值。

    关于ios - 具有静态间距的UIStackView子类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52188270/

    10-15 15:12