在 iOS Swift 中子类化 UIStackView 的弱 属性
Weak property for subclassing UIStackView in iOS Swift
我尝试子class 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!
我觉得classUIButtonHeaderView的实例和它的属性(container和titleLabel)可能有引用循环问题,所以我尝试在var前面加上weak,导致我的App崩溃.
Xcode 告诉我这一行
container.backgroundColor = .blue
错误信息出错
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
好像行
container = UIView()
创建classUIView实例失败,所以container为nil,导致App crash,不知道是什么原因
你必须创建可选项,因为当我们有一个 属性 持有对对象的弱引用时,它的类型应该是可选的,因为它有能力在运行时变为 nil。
weak var container: UIView?
weak var titleLabel: UILabel?
为了扩展 Khushbu 的回答,这个:
weak var container: UIView!
weak var titleLabel: UILabel!
表示(通过 weak
)如果对象被释放,您希望此值变为 nil
,并且(通过 !
)您保证永远不会访问它如果是nil
。这些是相互矛盾的。
要扩展 Rob 的回答,如果您将属性设为 weak 可选,您仍然会遇到问题。
当你这样说时:
container = UIView()
新创建的视图没有强引用,所以它会立即被释放并且container
会变成nil
,然后你才有机会将它添加到stackview。
要解决这个问题,您需要使用局部变量来保存 UIView
引用,直到它被添加为子视图;此时,堆栈视图将持有一个强引用,您可以将引用分配给您的 weak
属性 并让局部变量超出范围而不释放视图。
let newContainer = UIView()
newContainer.backgroundColor = .blue
addArrangedSubview(newContainer)
container = newContainer
我同意 Rob 的评论; subclassinf UIStackView
在这里可能不是正确的方法。
我尝试子class 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!
我觉得classUIButtonHeaderView的实例和它的属性(container和titleLabel)可能有引用循环问题,所以我尝试在var前面加上weak,导致我的App崩溃.
Xcode 告诉我这一行
container.backgroundColor = .blue
错误信息出错
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
好像行
container = UIView()
创建classUIView实例失败,所以container为nil,导致App crash,不知道是什么原因
你必须创建可选项,因为当我们有一个 属性 持有对对象的弱引用时,它的类型应该是可选的,因为它有能力在运行时变为 nil。
weak var container: UIView?
weak var titleLabel: UILabel?
为了扩展 Khushbu 的回答,这个:
weak var container: UIView!
weak var titleLabel: UILabel!
表示(通过 weak
)如果对象被释放,您希望此值变为 nil
,并且(通过 !
)您保证永远不会访问它如果是nil
。这些是相互矛盾的。
要扩展 Rob 的回答,如果您将属性设为 weak 可选,您仍然会遇到问题。
当你这样说时:
container = UIView()
新创建的视图没有强引用,所以它会立即被释放并且container
会变成nil
,然后你才有机会将它添加到stackview。
要解决这个问题,您需要使用局部变量来保存 UIView
引用,直到它被添加为子视图;此时,堆栈视图将持有一个强引用,您可以将引用分配给您的 weak
属性 并让局部变量超出范围而不释放视图。
let newContainer = UIView()
newContainer.backgroundColor = .blue
addArrangedSubview(newContainer)
container = newContainer
我同意 Rob 的评论; subclassinf UIStackView
在这里可能不是正确的方法。