Проблема
Я запускаю случайную анимацию для выбора UIViews с помощью таймера. Все анимации работают, как задумано, за исключением одной, в которой метод рисования CALayer вызывается после выхода из селектора таймера.
Подробное описание
Для ясности и упрощения позвольте мне схематизировать выполняемые действия.
Все созданные мной анимации работают так, как задумано: они представляют собой комбинацию CABasicAnimations на существующих подпредставлениях / подслоях или новых, добавленных в выбранную иерархию представлений. Они закодированы как расширение UIView, поэтому их можно вызывать в любых представлениях, независимо от представления или контроллера представления, в котором оно находится. Что ж, все работают, кроме одного.
Я действительно создал собственный класс CALayer, который состоит в рисовании шаблонов на CALayer. В расширении этого настраиваемого класса есть метод для анимации этих шаблонов (см. Ниже код). В общем, когда я дойду до шага / метода animate selected view
и запускаю эту конкретную анимацию, вот что должно произойти:
- вызывается метод с именем animatePattern
- этот метод добавляет настраиваемый класс CALayer к выбранному представлению, а затем вызывает расширение анимации этого слоя
Проблема: если со всеми другими анимациями все рисунки выполняются до выхода animate selected view
шага / метода, в этом конкретном случае метод рисования настраиваемого класса CALayer вызывается после выход из метода performAnimation
, что, в свою очередь, приводит к сбою анимации.
Я должен добавить, что я пробовал анимацию пользовательского класса CALayer на отдельной упрощенной игровой площадке, и она хорошо работает (я добавляю пользовательский слой к UIView
в методе viewDidLoad
UIViewController, а затем вызываю анимацию слоя в методе viewDidAppear
UIViewController.)
Код
метод, вызываемый
animate selected view
шагом / методом:func animatePattern(for duration: TimeInterval = 1) { let patternLayer = PatternLayer(effectType: .dark) patternLayer.frame = self.bounds self.layer.addSublayer(patternLayer) patternLayer.play(for: duration) }
(обратите внимание, что этот метод находится в расширении UIView, поэтому self
здесь представляет UIView, на котором была вызвана анимация)
упрощенный пользовательский класс 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
. Я должен пропустить что-то совершенно очевидное, но в настоящее время я бегаю по кругу, и я был бы признателен за свежий взгляд на это.
Заранее благодарим вас за то, что уделили время рассмотрению этого вопроса! Лучший,