我有一个UIView的子类,它使用一些使用Swift声明为ivars的NSLayoutConstraint实例。他们成为ivars的原因是我改变了常数值。其中一个与自我有关:
NSLayoutConstraint(item: self.contentView, attribute: .Right,
relatedBy: .Equal, toItem: self, attribute: .Right,
multiplier: 1, constant: self.contentViewWidth)
如您所知,所有ivars都应该在调用超类init之前初始化,但是只有在超类init之后才能引用self。此外,在初始化NSLayoutConstraint实例后,您无法更改toItem(第二项)值。
在Swift 1.2之前标记带有感叹号的ivar(隐式展开的值)告诉编译器你需要负责这个ivar是非零的,所以你可以在任何你想要的地方初始化ivar直到你确保在调用该代码之前不会使用它。这就是我使用的:我在super.init调用之后隐式解包并初始化了这个NSLayoutConstraint,因此可以引用self:
class FilterView: UIView, UITableViewDelegate, UITableViewDataSource {
private let contentRightConstraint : NSLayoutConstraint!
init(frame: CGRect, customMode: Bool = false) {
super.init(frame: CGRectZero)
contentRightConstraint = NSLayoutConstraint(item: self.contentView,
attribute: .Right, relatedBy: .Equal, toItem: self,
attribute: .Right, multiplier: 1, constant: self.contentViewWidth)
}
}
自Swift 1.2以来,上述解决方案不再适用。我找到了两个解决方法:
1)将let替换为var并使用虚拟值:
class FilterView: UIView, UITableViewDelegate, UITableViewDataSource {
private var contentRightConstraint = NSLayoutConstraint()
init(frame: CGRect, customMode: Bool = false) {
super.init(frame: CGRectZero)
contentRightConstraint = NSLayoutConstraint(item: self.contentView,
attribute: .Right, relatedBy: .Equal, toItem: self,
attribute: .Right, multiplier: 1, constant: self.contentViewWidth)
}
}
这不好,因为它使ivar变化并创建了一个不必要的实例。
2)使用懒惰的var:
class FilterView: UIView, UITableViewDelegate, UITableViewDataSource {
private lazy var contentRightConstraint : NSLayoutConstraint =
NSLayoutConstraint(item: self.contentView, attribute: .Right,
relatedBy: .Equal, toItem: self, attribute: .Right,
multiplier: 1, constant: self.contentViewWidth)
}
这样做会更好,但仍然可以更改let
。
有人有其他想法吗?