Ho implementato una classe LoadingLayer con alcuni elementi di animazione (2 per la precisione) animati con CABasicAnimation
. Ora, questa schermata di caricamento persiste in tutta l'intera applicazione. Nascondere la vista ferma tutte le animazioni? Oppure lasciami riformulare che: c'è molta memoria che devo essere preoccupata o che potrebbe potenzialmente causare ritardi? Ho provato ad utilizzare i metodi -pauseLayer:
e -resumeLayer:
ma hanno causato alcuni problemi dovuti al multithreading nella mia applicazione. È quindi giusto nascondere solo e mostrare la schermata di caricamento con le sue animazioni in esecuzione tutto il tempo?Mettere in pausa e riprendere CABasicAnimazione per la schermata di caricamento?
risposta
https://developer.apple.com/library/content/qa/qa1673/_index.html
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Se la vista è nascosto (invisibile o non nell'interfaccia a tutti), allora non fa parte della struttura di rendering.
Ma perché non interrompere semplicemente l'animazione quando il controller di visualizzazione nella cui vista questo livello è incorporato lascia l'interfaccia (viewDidDisappear
)? Dì semplicemente al livello removeAllAnimations
. Quindi creare nuovamente l'animazione, se lo si desidera, in viewWillAppear
?
Ecco la versione 3 rapida della risposta Nico's.
La speranza aiuta!
fileprivate func pauseLayer(layer: CALayer) {
let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}
fileprivate func resumeLayer(layer: CALayer) {
let pausedTime = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
layer.beginTime = timeSincePause
}
Estendere Nico 's risposta per modificare la velocità di qualsiasi variabile:
extension CALayer {
func udpate(speed newSpeed: Float) {
let newSpeed = newSpeed == 0 ? 1e-6 : newSpeed
let triggerTime = self.convertTime(CACurrentMediaTime(), from: nil)
let offset = self.timeOffset
let begin = self.beginTime
let speed = self.speed
self.beginTime = (triggerTime - offset)/Double(speed) + begin
self.timeOffset = triggerTime
self.speed = newSpeed
}
}
utilizzare questo approccio, se siete disposti a cambiare velocità di animazione strato in modo interattivo. Se si desidera interrompere completamente lo strato, è necessario utilizzare la risposta di Nico, anche se con questo metodo con speed=0.0
avrà effettivamente circa 11 giorni per le animazioni per finire, e in 1 ora di animazione progredirete su 0.0036
ho avuto una bella simile implementazione ma i tuoi lavori, grazie! –
Ok, no, in realtà ho avuto la stessa identica implementazione. Ma ora so perché ha smesso di funzionare di volta in volta. Ogni volta che l'applicazione va in background e la rilancio, le animazioni non riprenderanno più. Qualche idea di cosa potrebbe causare questo ? –
prova a cancellare le animazioni e leggerle su didBeomceActive – Nico