在iOS Swift中继承UIStackView的弱属性

时间:2018-05-16 12:50:02

标签: ios swift uilabel uistackview subclassing

我尝试将UIStackView子类化并添加一些我想要的控件。我添加一个UIView作为容器,所有其他视图,如UILabel,UIButton,UIImageView等,将作为子视图添加到容器中。

class UIButtonHeaderView: UIStackView {

    // MARK: - Properties

    var container: UIView!
    var titleLabel: UILabel!

    // MARK: - Initialization

    private func setUp() {
        // Set container.
        container = UIView()
        container.backgroundColor = .blue
        addArrangedSubview(container)

        // Set label.
        titleLabel = UILabel()
        container.addSubview(titleLabel)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true
        titleLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true
        titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor).isActive = true
        titleLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true
        titleLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true
        titleLabel.text = "This is just a simple test!!"
        titleLabel.backgroundColor = .green
        titleLabel.textColor = .red
        titleLabel.sizeToFit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        setUp()
    }
}

代码工作正常,但是当我替换

时我遇到了麻烦
var container: UIView!
var titleLabel: UILabel!

weak var container: UIView!
weak var titleLabel: UILabel!

我认为类UIButtonHeaderView的实例及其属性(container和titleLabel)可能有引用循环问题,所以我尝试在var前面添加弱,这会导致我的App崩溃。

Xcode告诉我这行

container.backgroundColor = .blue

错误消息错误

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

似乎就行了

container = UIView()

无法创建类UIView的实例,因此容器为nil,导致App崩溃,但我不知道原因。

3 个答案:

答案 0 :(得分:2)

你必须制作选项,因为当我们拥有一个包含对象弱引用的属性时,它的类型应该是可选的,因为它有能力在运行时变为nil。

weak var container: UIView?
weak var titleLabel: UILabel?

答案 1 :(得分:1)

要扩展Rob的答案,如果你的属性弱可选,你仍然会遇到问题。

当你这样说时:

container = UIView()

对新创建的视图没有强烈的引用,因此在您有机会将其添加到堆栈视图之前,它将立即发布并且container将变为nil

要解决此问题,您需要使用局部变量来保存UIView引用,直到将其添加为子视图;此时,堆栈视图将包含一个强引用,您可以将引用分配给weak属性,并让局部变量超出范围而不释放视图。

let newContainer = UIView()
newContainer.backgroundColor = .blue
addArrangedSubview(newContainer)
container = newContainer

我同意Rob的评论; subclassinf UIStackView可能不是正确的方法。

答案 2 :(得分:0)

要扩展Khushbu的答案,请:

weak var container: UIView!
weak var titleLabel: UILabel!

表示(通过weak),如果对象被释放,您希望此值变为nil,并且(通过!)您保证,如果它,您将永远不会访问它是nil。这些是相互矛盾的。