1

我正在尝试创建波纹管属性包装器

@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

有没有办法通过这个错误?

4

1 回答 1

0

您不能使用selfandimageViewHeightConstraint来初始化此属性,因为此时它不存在。

最简单的解决方案是将约束和视图传递给视图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
    }
}

或者,您可以使用 KeyPathimageViewHeightConstraint并传递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
    }
}
于 2020-03-06T09:11:22.473 回答