我正在尝试创建以下属性包装
@propertyWrapper
public struct ConstraintValue {
private let view:UIView
private let contraint:NSLayoutConstraint
public init(contraint:NSLayoutConstraint,view:UIView) {
self.contraint = contraint
self.view = view
}
public var wrappedValue: CGFloat {
set {
contraint.constant = newValue
view.layoutIfNeeded()
}
get {
return contraint.constant
}
}
}
但当我尝试使用它时,我会得到"不能在属性初始化器中使用实例成员;属性初始化器在"self"可用之前运行">
@IBOutlet weak private var imageViewHeightConstraint: NSLayoutConstraint!
@ConstraintValue(contraint: imageViewHeightConstraint, view: self)
public var imageHeight:CGFloat
有没有办法克服这个错误?
您不能使用self
和imageViewHeightConstraint
来初始化此属性,因为它目前不存在。
最简单的解决方案是在视图的init()
方法中将约束和视图传递给包装器,如下所示:
@propertyWrapper
public struct ConstraintValue {
var view: UIView!
var constraint: NSLayoutConstraint!
public var wrappedValue: CGFloat {
set {
constraint.constant = newValue
view.layoutIfNeeded()
}
get {
return constraint.constant
}
}
}
class OurView: UIView {
var imageViewHeightConstraint: NSLayoutConstraint!
@ConstraintValue public var imageHeight:CGFloat
init() {
super.init(size: .zero)
_imageHeight.view = self
_imageHeight.constraint = imageViewHeightConstraint
}
}
或者,您可以对imageViewHeightConstraint
使用KeyPath,并将self
传递给视图的init()
中的属性包装器。类似这样的东西:
protocol DynamicImageView: UIView {
var imageViewHeightConstraint: NSLayoutConstraint! { get set }
}
@propertyWrapper
public struct ConstraintValue {
var view: DynamicImageView?
private let constraintKeyPath: WritableKeyPath<DynamicImageView, NSLayoutConstraint>
init(constraintKeyPath: WritableKeyPath<DynamicImageView, NSLayoutConstraint>) {
self.constraintKeyPath = constraintKeyPath
}
public var wrappedValue: CGFloat {
set {
view?[keyPath: constraintKeyPath].constant = newValue
view?.layoutIfNeeded()
}
get {
view?[keyPath: constraintKeyPath].constant ?? 0.0
}
}
}
class OurView: UIView, DynamicImageView{
var imageViewHeightConstraint: NSLayoutConstraint!
@ConstraintValue(constraintKeyPath: .imageViewHeightConstraint)
public var imageHeight:CGFloat
init() {
super.init(frame: .zero)
_imageHeight.view = self
}
}