Оболочки свойств: «Невозможно использовать элемент экземпляра в инициализаторе свойства; инициализаторы свойства запускаются до того, как станет доступно« self »» - PullRequest
1 голос
/ 06 марта 2020

Я пытаюсь создать нижеприведенную оболочку свойства

@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

Есть ли способ выполнить эту ошибку?

1 Ответ

0 голосов
/ 06 марта 2020

Вы не можете использовать 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
    }
}

В качестве альтернативы вы можете использовать KeyPath для imageViewHeightConstraint и передать 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
    }
}
...