Я запускаю случайную анимацию для выбранных UIViews с помощью таймера. Все анимации работают так, как задумано, за исключением одной, в которой метод рисования CALayer вызывается после выхода из селектора таймера.
Подробное описание
Для наглядности и упрощения схематизирую выполняемые действия.

Все анимации, которые я создал на данный момент, работают так, как задумано: они представляют собой комбинацию CABasicAnimations в существующих подпредставлениях/подслоях или в новых, добавленных в выбранную иерархию представлений. Они закодированы как расширение UIView, поэтому их можно вызывать в любых представлениях, независимо от представления или контроллера представления, в котором оно находится. Ну, все работают, кроме одного.
Я действительно создал собственный класс CALayer, который предназначен для рисования шаблонов на CALayer. В расширении этого пользовательского класса имеется метод для анимации этих шаблонов (см. код ниже). В общем, когда я дойду до шага/метода анимации выбранного представления и запущу эту конкретную анимацию, вот что должно произойти:
- вызывается метод с именем animatePattern
- этот метод добавляет пользовательский класс CALayer в выбранное представление, а затем вызывает расширение анимации этого слоя
Я должен добавить, что я попробовал анимацию пользовательского класса CALayer в отдельной и упрощенной игровой площадке, и она работает хорошо (я добавляю собственный слой в UIView
code> в методе viewDidLoad UIViewController, а затем я вызываю анимацию слоя в методе viewDidAppear UIViewController.)
Код< /strong>
- метод, вызываемый анимацией выбранного представления шаг/метод:
Код: Выделить всё
func animatePattern(for duration: TimeInterval = 1) { let patternLayer = PatternLayer(effectType: .dark) patternLayer.frame = self.bounds self.layer.addSublayer(patternLayer) patternLayer.play(for: duration) }
- упрощенный пользовательский класс CALayer:
Код: Выделить всё
override var bounds: CGRect { didSet { self.setNeedsDisplay() } // Initializers override init() { super.init() self.setNeedsDisplay() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } init(effectType: EffectType){ super.init() // sets various properties self.setNeedsDisplay() } // Drawing override func draw(in ctx: CGContext) { super.draw(in: ctx) guard self.frame != CGRect.zero else { return } self.masksToBounds = true // do the drawings }
- расширение анимации пользовательского класса CALayer:
Код: Выделить всё
func play(for duration: Double, removeAfterCompletion: RemoveAfterCompletion = .no) { guard self.bounds != CGRect.zero else { print("Cannot animate nil layer") return } CATransaction.begin() CATransaction.setCompletionBlock { if removeAfterCompletion.removeStatus { if case RemoveAfterCompletion.yes = removeAfterCompletion { self.fadeOutDuration = 0.0 } self.fadeToDisappear(duration: &self.fadeOutDuration) } } // perform animations CATransaction.commit() }
Я пытался принудительно отрисовать слой, вставив setNeedsDisplay / setNeedsLayout в разные места кода, но это не сработало: отладка метода draw пользовательского класса CALayer постоянно достигается после выход метода PerformAnimation, хотя его следует вызывать, когда кадр слоя изменяется в методе animatePattern. Должно быть, я упустил что-то совершенно очевидное, но в настоящее время я бегаю по кругу, и я был бы признателен за свежий взгляд на это.
Заранее спасибо, что нашли время, чтобы рассмотрите этот вопрос!
С наилучшими пожеланиями,
Подробнее здесь: https://stackoverflow.com/questions/546 ... ed-earlier