Попытка изменить анимационные свойства во время анимации?

При a CALayer,

который анимируется,

class Test: CAGradientLayer {

    override func draw(in ctx: CGContext) {

        super.draw(in: ctx)
        startPoint = ....
    }

*** Завершение приложения из-за неперехваченного исключения "CALayerReadOnly", причина: "попытка изменить уровень только для чтения

Кажется невозможным изменить один из обычных анимационных свойств внутри вызова draw#inContext.

Итак, например:

Легко и просто иметь собственное настраиваемое собственное свойство, а затем нарисовать что-то на основе этого. Здесь некоторый код для свойства .progress,

qaru.site/info/561711/...

при анимации вашего свойства .progress было бы легко представить, что нужно устанавливать другие свойства слоя, используя некоторую формулу, основанную на значении .progress для каждого кадра.

Однако вы не можете сделать это в функции draw#in - как это сделать?

Ответ 1

Когда CoreAnimation выполняет анимацию, он создает теневые копии слоя, и каждая копия будет отображаться в другом кадре. Копии, созданные -initWithLayer:. Копии, созданные этим методом, доступны только для чтения. Вот почему вы получаете исключение только для чтения.

Вы можете переопределить этот метод для создания собственных копий требуемых свойств. Например:

    override init(layer: Any) {
    super.init(layer: layer)
    // Check class
    if let myLayer = layer as? CircleProgressLayer {
        // Copy the value
        startPoint = myLayer.startPoint
    }
}

Вместо установки self.startPoint вы должны написать self.model.startPoint = ..., потому что все копии презентации имеют одну и ту же модель.

Обратите внимание, что вы должны это делать и при чтении переменной, а не только при ее установке. Для полноты нужно указать также представление свойства, которое вместо этого отображает текущий (копию) слоя.

Ссылка на Документация Apple