7

I have implemented a LoadingLayer class that has some animating elements (2 to be exact) which are animated with CABasicAnimation. Now, this loading screen view persists throughout the whole application. Does hiding the view stop all animations ? Or let me rephrase that: Is there a lot of memory I have to be worried about or could that potentially cause lags ? I tried to use the -pauseLayer: and -resumeLayer: methods but they caused some problems due to multithreading in my application. Is it therefore ok just to hide and show the loading screen with its animations running all the time ?

the_critic
  • 12,720
  • 19
  • 67
  • 115

4 Answers4

10

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;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Nico
  • 3,826
  • 1
  • 21
  • 31
  • I had a pretty similar implementation but yours works, thank you ! – the_critic Apr 03 '13 at 16:43
  • Okay, no, actually I had the exact same implementation. But now I know why it stopped working from time to time. Whenever the application goes into background and I relaunch it the animations would not resume again. Any idea what could be causing this ? – the_critic Apr 04 '13 at 13:12
  • 1
    try clearing out the animations and readding them on didBeomceActive – Nico Apr 04 '13 at 14:14
  • I think these animations might be cleared due to ARC. However, I just add them anew whenever `-viewWillAppear:` is called and clear them when `-viewWillDisappear:` is called. – the_critic Apr 04 '13 at 14:26
4

Here is the swift 3 version of Nico's answer.

Hope helps!

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
}
chiri
  • 153
  • 1
  • 6
0

If the view is hidden (invisible or not in the interface at all), then it is not part of the render tree.

But why not simply stop the animation when the view controller in whose view this layer is embedded leaves the interface (viewDidDisappear)? Just tell the layer to removeAllAnimations. Then create the animation anew, if desired, in viewWillAppear?

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

Extending Nico's answer for modifying speed to any variable:

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
    }
}

Use this approach, if you're willing to change layer animation speed interactively. If you want to Completely stop the layer, you should use Nico's answer, although using this method with speed=0.0 will actually take about 11 days for animations to finish, and in 1hour animation will progress about 0.0036

farzadshbfn
  • 2,710
  • 1
  • 18
  • 38