ios 当应用程序从后台恢复时,在停止的地方恢复动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7568567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Restoring animation where it left off when app resumes from background
提问by Palimondo
I have an endlessly looping CABasicAnimation
of a repeating image tile in my view:
CABasicAnimation
在我看来,我有一个无限循环的重复图像图块:
a = [CABasicAnimation animationWithKeyPath:@"position"];
a.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear];
a.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
a.toValue = [NSValue valueWithCGPoint:CGPointMake(image.size.width, 0)];
a.repeatCount = HUGE_VALF;
a.duration = 15.0;
[a retain];
I have tried to "pause and resume" the layer animation as described in Technical Q&A QA1673.
我已尝试“暂停和恢复”图层动画,如技术问答 QA1673 中所述。
When the app enters background, the animation gets removed from the layer.
To compensate I listen to UIApplicationDidEnterBackgroundNotification
and call stopAnimation
and in response to UIApplicationWillEnterForegroundNotification
call startAnimation
.
当应用程序进入后台时,动画会从图层中移除。为了补偿我听UIApplicationDidEnterBackgroundNotification
和调用stopAnimation
并响应UIApplicationWillEnterForegroundNotification
调用startAnimation
。
- (void)startAnimation
{
if ([[self.layer animationKeys] count] == 0)
[self.layer addAnimation:a forKey:@"position"];
CFTimeInterval pausedTime = [self.layer timeOffset];
self.layer.speed = 1.0;
self.layer.timeOffset = 0.0;
self.layer.beginTime = 0.0;
CFTimeInterval timeSincePause =
[self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
self.layer.beginTime = timeSincePause;
}
- (void)stopAnimation
{
CFTimeInterval pausedTime =
[self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
self.layer.speed = 0.0;
self.layer.timeOffset = pausedTime;
}
The problem is that it starts again at the beginning and there is ugly jump from last position, as seen on app snapshot the system took when application did enter background, back to the start of the animation loop.
问题是它在开始时再次开始,并且从最后一个位置有一个丑陋的跳转,如应用程序进入后台时系统拍摄的应用程序快照所示,回到动画循环的开始。
I can not figure out how to make it start at last position, when I re-add the animation. Frankly, I just don't understand how that code from QA1673 works: in resumeLayer
it sets the layer.beginTime twice, which seems redundant. But when I've removed the first set-to-zero, it did not resume the animation where it was paused. This was tested with simple tap gesture recognizer, that did toggle the animation - this is not strictly related to my issues with restoring from background.
当我重新添加动画时,我不知道如何让它从最后一个位置开始。坦率地说,我只是不明白 QA1673 中的代码是如何工作的:在resumeLayer
其中将 layer.beginTime 设置了两次,这似乎是多余的。但是当我删除第一个设置为零时,它没有恢复暂停的动画。这是用简单的点击手势识别器测试的,它确实切换了动画——这与我从后台恢复的问题没有严格的关系。
What state should I remember before the animation gets removed and how do I restore the animation from that state, when I re-add it later?
在动画被移除之前我应该记住什么状态,以及当我稍后重新添加动画时如何从该状态恢复动画?
采纳答案by Max MacLeod
After quite a lot of searching and talks with iOS development gurus, it appears that QA1673doesn't help when it comes to pausing, backgrounding, then moving to foreground. My experimentation even shows that delegate methods that fire off from animations, such asanimationDidStop
become unreliable.
在与 iOS 开发大师进行了大量搜索和交谈之后,QA1673似乎在暂停、后台、然后移动到前台时没有帮助。我的实验甚至表明从动画中触发的委托方法animationDidStop
变得不可靠。
Sometimes they fire, sometimes they don't.
有时他们会开火,有时他们不会。
This creates a lot of problems because it means that, not only are you looking at a different screen that you were when you paused, but also the sequence of events currently in motion can be disrupted.
这会产生很多问题,因为这意味着,您不仅看到的是与暂停时不同的屏幕,而且当前正在运行的事件序列也可能被打乱。
My solution thus far has been as follows:
到目前为止,我的解决方案如下:
When the animation starts, I get the start time:
当动画开始时,我得到开始时间:
mStartTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
mStartTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
When the user hits the pause button, I remove the animation from theCALayer
:
当用户点击暂停按钮时,我从 中删除动画CALayer
:
[layer removeAnimationForKey:key];
[layer removeAnimationForKey:key];
I get the absolute time usingCACurrentMediaTime()
:
我使用CACurrentMediaTime()
以下方法获得绝对时间:
CFTimeInterval stopTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
CFTimeInterval stopTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
Using themStartTime
andstopTime
I calculate an offset time:
使用mStartTime
和stopTime
我计算偏移时间:
mTimeOffset = stopTime - mStartTime;
I also set the model values of the object to be that of thepresentationLayer
. So, mystop
method looks like this:
我还将对象的模型值设置为presentationLayer
. 所以,我的stop
方法是这样的:
//--------------------------------------------------------------------------------------------------
- (void)stop
{
const CALayer *presentationLayer = layer.presentationLayer;
layer.bounds = presentationLayer.bounds;
layer.opacity = presentationLayer.opacity;
layer.contentsRect = presentationLayer.contentsRect;
layer.position = presentationLayer.position;
[layer removeAnimationForKey:key];
CFTimeInterval stopTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
mTimeOffset = stopTime - mStartTime;
}
On resume, I recalculate what's left of the paused animation based upon themTimeOffset
. That's a bit messy because I'm usingCAKeyframeAnimation
. I figure out what keyframes are outstanding based on themTimeOffset
. Also, I take into account that the pause may have occurred mid frame, e.g. halfway betweenf1
andf2
. That time is deducted from the time of that keyframe.
在恢复时,我根据mTimeOffset
. 这有点乱,因为我正在使用CAKeyframeAnimation
. 我根据mTimeOffset
. 此外,我考虑到暂停可能发生在帧中间,例如在f1
和之间f2
。该时间从该关键帧的时间中扣除。
I then add this animation to the layer afresh:
然后我将这个动画重新添加到图层中:
[layer addAnimation:animationGroup forKey:key];
[layer addAnimation:animationGroup forKey:key];
The other thing to remember is that you will need to check the flag inanimationDidStop
and only remove the animated layer from the parent withremoveFromSuperlayer
if the flag isYES
. That means that the layer is still visible during the pause.
另一件要记住的事情是,您需要检查标志,animationDidStop
并且removeFromSuperlayer
如果标志是YES
. 这意味着该层在暂停期间仍然可见。
This method does seem very laborious. It does work though! I'd love to be able to simply do this using QA1673. But at the moment for backgrounding, it doesn't work and this seems to be the only solution.
这种方法看起来确实很费力。不过它确实有效!我希望能够使用QA1673简单地做到这一点。但目前对于背景,它不起作用,这似乎是唯一的解决方案。
回答by cclogg
Hey I had stumbled upon the same thing in my game, and ended up finding a somewhat different solution than you, which you may like :) I figured I should share the workaround I found...
嘿,我在我的游戏中偶然发现了同样的事情,最终找到了一个与你有些不同的解决方案,你可能会喜欢:) 我想我应该分享我找到的解决方法......
My case is using UIView/UIImageView animations, but it's basically still CAAnimations at its core... The gist of my method is that I copy/store the current animation on a view, and then let Apple's pause/resume work still, but before resuming I add my animation back on. So let me present this simple example:
我的情况是使用 UIView/UIImageView 动画,但它基本上仍然是 CAAnimations 的核心......我的方法的要点是我将当前动画复制/存储在一个视图上,然后让 Apple 的暂停/恢复继续工作,但在此之前恢复我添加我的动画。所以让我展示这个简单的例子:
Let's say I have a UIView called movingView. The UIView's center is animated via the standard [UIView animateWithDuration...] call. Using the mentioned QA1673code, it works great pausing/resuming (when not exiting the app)... but regardless, I soon realized that on exit, whether I pause or not, the animation was completely removed... and here I was in your position.
假设我有一个名为movingView的UIView 。UIView 的中心通过标准的 [ UIView animateWithDuration...] 调用进行动画处理。使用提到的QA1673代码,它可以很好地暂停/恢复(当不退出应用程序时)......但无论如何,我很快意识到在退出时,无论我是否暂停,动画都被完全删除......我在这里在你的位置。
So with this example, here's what I did:
所以在这个例子中,这就是我所做的:
- Have a variable in your header file called something like animationViewPosition, of type *CAAnimation**.
When the app exits to background, I do this:
animationViewPosition = [[movingView.layer animationForKey:@"position"] copy]; // I know position is the key in this case... [self pauseLayer:movingView.layer]; // this is the Apple method from QA1673
- Note: Those 2 ^ calls are in a method that is the handler for the UIApplicationDidEnterBackgroundNotification(similar to you)
- Note 2: If you don't know what the key is (of your animation), you can loop through the view's layer's 'animationKeys' property and log those out (mid animation presumably).
Now in my UIApplicationWillEnterForegroundNotificationhandler:
if (animationViewPosition != nil) { [movingView.layer addAnimation:animationViewPosition forKey:@"position"]; // re-add the core animation to the view [animationViewPosition release]; // since we 'copied' earlier animationViewPosition = nil; } [self resumeLayer:movingView.layer]; // Apple's method, which will resume the animation at the position it was at when the app exited
- 在你的头文件中有一个名为animationViewPosition的变量,类型为 *CAAnimation**。
当应用程序退出到后台时,我这样做:
animationViewPosition = [[movingView.layer animationForKey:@"position"] copy]; // I know position is the key in this case... [self pauseLayer:movingView.layer]; // this is the Apple method from QA1673
- 注意:这 2 个 ^ 调用位于UIApplicationDidEnterBackgroundNotification处理程序的方法中(与您类似)
- 注意 2:如果您不知道(动画的)关键是什么,您可以遍历视图层的“ animationKeys”属性并将它们注销(大概是动画中间)。
现在在我的UIApplicationWillEnterForegroundNotification处理程序中:
if (animationViewPosition != nil) { [movingView.layer addAnimation:animationViewPosition forKey:@"position"]; // re-add the core animation to the view [animationViewPosition release]; // since we 'copied' earlier animationViewPosition = nil; } [self resumeLayer:movingView.layer]; // Apple's method, which will resume the animation at the position it was at when the app exited
And that's pretty much it! It has worked for me so far :)
仅此而已!到目前为止它对我有用:)
You can easily extend it for more animations or views by just repeating those steps for each animation. It even works for pausing/resuming UIImageView animations, ie the standard [imageView startAnimating]. The layer animation key for that (by the way) is "contents".
您只需为每个动画重复这些步骤,就可以轻松地将其扩展为更多动画或视图。它甚至适用于暂停/恢复 UIImageView 动画,即标准的 [ imageView startAnimating]。层动画关键(顺便说一下)是“内容”。
Listing 1 Pause and Resume animations.
清单 1 暂停和恢复动画。
-(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;
}
回答by Matej Bukovinski
It's surprising to see that this isn't more straightforward. I created a category, based on cclogg's approach, that should make this a one-liner.
令人惊讶的是,这并不简单。我根据 cclogg 的方法创建了一个类别,这应该使它成为一个单行。
CALayer+MBAnimationPersistence
CALayer+MBAnimationPersistence
Simply invoke MB_setCurrentAnimationsPersistent
on your layer after setting up the desired animations.
MB_setCurrentAnimationsPersistent
设置所需的动画后,只需在您的图层上调用。
[movingView.layer MB_setCurrentAnimationsPersistent];
Or specify the animations that should be persisted explicitly.
或者指定应该显式持久化的动画。
movingView.layer.MB_persistentAnimationKeys = @[@"position"];
回答by Pepijn
I can't comment so I will add it as an answer.
I used cclogg's solution but my app was crashing when the animation's view was removed from his superview, added again, and then going to background.
The animation was made infinite by setting animation.repeatCount
to Float.infinity
.
The solution I had was to set animation.removedOnCompletion
to false
.
It's very weird that it works because the animation is never completed. If anyone has an explanation, I like to hear it.
Another tip: If you remove the view from its superview. Don't forget to remove the observer by calling NSNotificationCenter.defaultCenter().removeObserver(...)
.
我无法发表评论,因此我会将其添加为答案。
我使用了 cclogg 的解决方案,但是当动画的视图从他的超级视图中删除,再次添加,然后转到后台时,我的应用程序崩溃了。
通过设置animation.repeatCount
为,动画变得无限Float.infinity
。
我的解决方案是设置animation.removedOnCompletion
为false
.
它的工作原理很奇怪,因为动画从未完成。如果有人有解释,我喜欢听。
另一个提示:如果您从其超级视图中删除视图。不要忘记通过调用删除观察者NSNotificationCenter.defaultCenter().removeObserver(...)
。
回答by ArtFeel
I write a Swift 4.2version extension based on @cclogg and @Matej Bukovinski answers. All you need is to call layer.makeAnimationsPersistent()
我根据@cclogg 和@Matej Bukovinski 的回答编写了一个Swift 4.2版本扩展。你只需要打电话layer.makeAnimationsPersistent()
Full Gist here: CALayer+AnimationPlayback.swift, CALayer+PersistentAnimations.swift
完整要点在这里:CALayer+AnimationPlayback.swift, CALayer+PersistentAnimations.swift
Core part:
核心部分:
public extension CALayer {
static private var persistentHelperKey = "CALayer.LayerPersistentHelper"
public func makeAnimationsPersistent() {
var object = objc_getAssociatedObject(self, &CALayer.persistentHelperKey)
if object == nil {
object = LayerPersistentHelper(with: self)
let nonatomic = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
objc_setAssociatedObject(self, &CALayer.persistentHelperKey, object, nonatomic)
}
}
}
public class LayerPersistentHelper {
private var persistentAnimations: [String: CAAnimation] = [:]
private var persistentSpeed: Float = 0.0
private weak var layer: CALayer?
public init(with layer: CALayer) {
self.layer = layer
addNotificationObservers()
}
deinit {
removeNotificationObservers()
}
}
private extension LayerPersistentHelper {
func addNotificationObservers() {
let center = NotificationCenter.default
let enterForeground = UIApplication.willEnterForegroundNotification
let enterBackground = UIApplication.didEnterBackgroundNotification
center.addObserver(self, selector: #selector(didBecomeActive), name: enterForeground, object: nil)
center.addObserver(self, selector: #selector(willResignActive), name: enterBackground, object: nil)
}
func removeNotificationObservers() {
NotificationCenter.default.removeObserver(self)
}
func persistAnimations(with keys: [String]?) {
guard let layer = self.layer else { return }
keys?.forEach { (key) in
if let animation = layer.animation(forKey: key) {
persistentAnimations[key] = animation
}
}
}
func restoreAnimations(with keys: [String]?) {
guard let layer = self.layer else { return }
keys?.forEach { (key) in
if let animation = persistentAnimations[key] {
layer.add(animation, forKey: key)
}
}
}
}
@objc extension LayerPersistentHelper {
func didBecomeActive() {
guard let layer = self.layer else { return }
restoreAnimations(with: Array(persistentAnimations.keys))
persistentAnimations.removeAll()
if persistentSpeed == 1.0 { // if layer was playing before background, resume it
layer.resumeAnimations()
}
}
func willResignActive() {
guard let layer = self.layer else { return }
persistentSpeed = layer.speed
layer.speed = 1.0 // in case layer was paused from outside, set speed to 1.0 to get all animations
persistAnimations(with: layer.animationKeys())
layer.speed = persistentSpeed // restore original speed
layer.pauseAnimations()
}
}
回答by Grzegorz Krukowski
Just in case anyone needs a Swift 3 solution for this problem:
以防万一有人需要 Swift 3 解决方案来解决这个问题:
All you have to do is to subclass your animated view from this class. It always persist and resume all animations on it's layer.
你所要做的就是从这个类中继承你的动画视图。它始终保持并恢复其图层上的所有动画。
class ViewWithPersistentAnimations : UIView {
private var persistentAnimations: [String: CAAnimation] = [:]
private var persistentSpeed: Float = 0.0
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
func commonInit() {
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func didBecomeActive() {
self.restoreAnimations(withKeys: Array(self.persistentAnimations.keys))
self.persistentAnimations.removeAll()
if self.persistentSpeed == 1.0 { //if layer was plaiyng before backgorund, resume it
self.layer.resume()
}
}
func willResignActive() {
self.persistentSpeed = self.layer.speed
self.layer.speed = 1.0 //in case layer was paused from outside, set speed to 1.0 to get all animations
self.persistAnimations(withKeys: self.layer.animationKeys())
self.layer.speed = self.persistentSpeed //restore original speed
self.layer.pause()
}
func persistAnimations(withKeys: [String]?) {
withKeys?.forEach({ (key) in
if let animation = self.layer.animation(forKey: key) {
self.persistentAnimations[key] = animation
}
})
}
func restoreAnimations(withKeys: [String]?) {
withKeys?.forEach { key in
if let persistentAnimation = self.persistentAnimations[key] {
self.layer.add(persistentAnimation, forKey: key)
}
}
}
}
extension CALayer {
func pause() {
if self.isPaused() == false {
let pausedTime: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil)
self.speed = 0.0
self.timeOffset = pausedTime
}
}
func isPaused() -> Bool {
return self.speed == 0.0
}
func resume() {
let pausedTime: CFTimeInterval = self.timeOffset
self.speed = 1.0
self.timeOffset = 0.0
self.beginTime = 0.0
let timeSincePause: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
self.beginTime = timeSincePause
}
}
On Gist: https://gist.github.com/grzegorzkrukowski/a5ed8b38bec548f9620bb95665c06128
关于要点:https: //gist.github.com/grzegorzkrukowski/a5ed8b38bec548f9620bb95665c06128
回答by Warpling
I was able to restore the animation (but not the animation position) by saving a copy of the current animation and adding it back on resume. I called startAnimation on load and when entering the foreground and pause when entering the background.
我能够通过保存当前动画的副本并将其添加回恢复来恢复动画(但不是动画位置)。我在加载和进入前台时调用 startAnimation 并在进入后台时暂停。
- (void) startAnimation {
// On first call, setup our ivar
if (!self.myAnimation) {
self.myAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
/*
Finish setting up myAnimation
*/
}
// Add the animation to the layer if it hasn't been or got removed
if (![self.layer animationForKey:@"myAnimation"]) {
[self.layer addAnimation:self.spinAnimation forKey:@"myAnimation"];
}
}
- (void) pauseAnimation {
// Save the current state of the animation
// when we call startAnimation again, this saved animation will be added/restored
self.myAnimation = [[self.layer animationForKey:@"myAnimation"] copy];
}
回答by BTGunner
I use cclogg's solution to great effect. I also wanted to share some additional info that might help someone else, because it frustrated me for a while.
我使用 cclogg 的解决方案效果很好。我还想分享一些可能对其他人有所帮助的其他信息,因为这让我感到沮丧了一段时间。
In my app I have a number of animations, some that loop forever, some that run only once and are spawned randomly. cclogg's solution worked for me, but when I added some code to
在我的应用程序中,我有许多动画,有些会永远循环,有些只运行一次并随机生成。cclogg 的解决方案对我有用,但是当我添加一些代码到
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
in order to do something when only the one-time animations were finished, this code would trigger when I resumed my app (using cclogg's solution) whenever those specific one-time animations were running when it was paused. So I added a flag (a member variable of my custom UIImageView class) and set it to YES in the section where you resume all the layer animations (resumeLayer
in cclogg's, analogous to Apple solution QA1673) to keep this from happening. I do this for every UIImageView that is resuming. Then, in the animationDidStop
method, only run the one-time animation handling code when that flag is NO. If it's YES, ignore the handling code. Switch the flag back to NO either way. That way when the animation truly finishes, your handling code will run. So like this:
为了在仅一次性动画完成时执行某些操作,只要那些特定的一次性动画在暂停时正在运行,就会在我恢复我的应用程序(使用 cloggg 的解决方案)时触发此代码。因此,我添加了一个标志(我的自定义 UIImageView 类的成员变量),并在您恢复所有图层动画的部分(resumeLayer
在 clogg 中,类似于 Apple 解决方案 QA1673)将其设置为 YES以防止这种情况发生。我为每个正在恢复的 UIImageView 执行此操作。然后,在该animationDidStop
方法中,仅当该标志为 NO 时才运行一次性动画处理代码。如果是,则忽略处理代码。无论哪种方式,将标志切换回 NO。这样,当动画真正完成时,您的处理代码就会运行。所以像这样:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
if (!resumeFlag) {
// do something now that the animation is finished for reals
}
resumeFlag = NO;
}
Hope that helps someone.
希望能帮助某人。
回答by George_E
I was recognizing the gesture state like so:
我像这样识别手势状态:
// Perform action depending on the state
switch gesture.state {
case .changed:
// Some action
case .ended:
// Another action
// Ignore any other state
default:
break
}
All I needed to do was change the .ended
case to .ended, .cancelled
.
我需要做的就是将.ended
案例更改为.ended, .cancelled
.
回答by sash
iOS will remove all animations when view disappears from the visible area (not only when app goes into background). To fix it I created custom CALayer
subclass and overrided 2 methods so the system doesn't remove animations - removeAnimation
and removeAllAnimations
:
当视图从可见区域消失时(不仅是当应用程序进入后台时),iOS 将删除所有动画。为了修复它,我创建了自定义CALayer
子类并覆盖了 2 个方法,因此系统不会删除动画 -removeAnimation
和removeAllAnimations
:
class CustomCALayer: CALayer {
override func removeAnimation(forKey key: String) {
// prevent iOS to clear animation when view is not visible
}
override func removeAllAnimations() {
// prevent iOS to clear animation when view is not visible
}
func forceRemoveAnimation(forKey key: String) {
super.removeAnimation(forKey: key)
}
}
In the view where you want this layer to be used as main layer override layerClass
property:
在您希望将此图层用作主图层覆盖layerClass
属性的视图中:
override class var layerClass: AnyClass {
return CustomCALayer.self
}
To pause and resume animation:
暂停和恢复动画:
extension CALayer {
func pause() {
guard self.isPaused() == false else {
return
}
let pausedTime: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil)
self.speed = 0.0
self.timeOffset = pausedTime
}
func resume() {
guard self.isPaused() else {
return
}
let pausedTime: CFTimeInterval = self.timeOffset
self.speed = 1.0
self.timeOffset = 0.0
self.beginTime = 0.0
self.beginTime = self.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
}
func isPaused() -> Bool {
return self.speed == 0.0
}
}