Как продолжить анимация после пробуждения приложения?
Я использую этот код для создания вращающейся анимации в своем приложении:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver( self, selector: #selector(ViewController.applicationDidBecomeActive(notification:)),
name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
NotificationCenter.default.addObserver( self, selector: #selector(ViewController.applicationDidEnterBackground(notification:)), name:NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
animationStatus(true)
}
func animationStatus(_ enable: Bool) {
if enable {
if vinylStatus == "true" {
resumeLayer(layer: vinylView.layer)
} else {
rotateImageView()
resumeLayer(layer: vinylView.layer)
}
} else {
pauseLayer(layer: vinylView.layer)
}
}
func rotateImageView() {
vinylStatus = "true"
UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
self.vinylView.transform = self.vinylView.transform.rotated(by: .pi / 2)
}) { (finished) in
if finished {
self.rotateImageView()
}
}
}
func pauseLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}
func resumeLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
layer.beginTime = timeSincePause
}
Но я хочу продолжить анимацию после того, как приложение было скрыто и повторно развернуто, и я использую этот код, но анимация останавливается и не работает. Как исправить эту проблему?
@objc func applicationDidBecomeActive(notification: NSNotification) {
print ("applicationDidBecomeActive")
}
@objc func applicationDidEnterBackground(notification: NSNotification) {
//pauseLayer(layer: vinylView.layer)
}
}
Я не понимаю. Например, в applicationDidBecomeActive у меня есть только этот код:print ("applicationDidBecomeActive"). И если я открываю центр управления или центр уведомлений и возвращаюсь в приложение во время отладки, я получаю это applicationDidBecomeActive, но моя анимация не останавливается. Но если я сверну приложение и вернусь или заблокирую iPhone и вернусь в приложение, я тоже получу это в отладке applicationDidBecomeActive, но в этом случае анимация останавливается. Почему так происходит?
Ответы (1 шт):
Работающее решение с использованием CABasicAnimation, сделано на основе этого ответа - запуск и возобновление анимации вращения с помощью кнопки или при сворачивании/разворачивании приложения
Расширение
extension UIView {
/**
Will rotate `self` for ever.
- Parameter duration: The duration in seconds of a complete rotation (360º).
- Parameter clockwise: If false, will rotate counter-clockwise.
*/
func startRotating(duration: Double, clockwise: Bool) {
let kAnimationKey = "rotation"
var currentState = CGFloat(0)
// Get current state
if let presentationLayer = layer.presentation(),
let zValue = presentationLayer.value(forKeyPath: "transform.rotation.z") {
currentState = CGFloat((zValue as AnyObject).floatValue)
}
if self.layer.animation(forKey: kAnimationKey) == nil {
let animate = CABasicAnimation(keyPath: "transform.rotation")
animate.duration = duration
animate.repeatCount = Float.infinity
animate.fromValue = currentState // Should the value be nil, will start from 0 a.k.a. "the beginning".
animate.byValue = clockwise ? Float(.pi * 2.0) : -Float(.pi * 2.0)
self.layer.add(animate, forKey: kAnimationKey)
}
}
/// Will stop a `startRotating(duration: _, clockwise: _)` instance.
func stopRotating() {
let kAnimationKey = "rotation"
var currentState = CGFloat(0)
// Get current state
if let presentationLayer = layer.presentation(),
let zValue = presentationLayer.value(forKeyPath: "transform.rotation.z") {
currentState = CGFloat((zValue as AnyObject).floatValue)
}
if self.layer.animation(forKey: kAnimationKey) != nil {
self.layer.removeAnimation(forKey: kAnimationKey)
}
// Leave self as it was when stopped.
layer.transform = CATransform3DMakeRotation(currentState, 0, 0, 1)
}
}
Пример
class ViewController: UIViewController {
var rotationButton: UIButton!
var rotatingView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive(notification:)),
name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidEnterBackground(notification:)),
name:UIApplication.didEnterBackgroundNotification, object: nil)
setupUI()
}
func setupUI() {
rotationButton = UIButton(type: .system)
rotationButton.setTitle("Start rotation", for: .normal)
rotationButton.setTitle("Stop rotation", for: .selected)
rotationButton.addTarget(self, action: #selector(rotationButtonTouchUpInside(_ :)), for: .touchUpInside)
rotationButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(rotationButton)
rotationButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 32).isActive = true
rotationButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
rotatingView = UIView()
rotatingView.backgroundColor = .red
view.addSubview(rotatingView)
rotatingView.translatesAutoresizingMaskIntoConstraints = false
rotatingView.widthAnchor.constraint(equalToConstant: 150).isActive = true
rotatingView.heightAnchor.constraint(equalToConstant: 150).isActive = true
rotatingView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
rotatingView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
@objc func applicationDidBecomeActive(notification: NSNotification) {
print(#function)
rotationButton.isSelected = true
rotatingView.startRotating(duration: 3, clockwise: true)
}
@objc func applicationDidEnterBackground(notification: NSNotification) {
print(#function)
rotationButton.isSelected = false
rotatingView.stopRotating()
}
@objc func rotationButtonTouchUpInside(_ sender: UIButton) {
if sender.isSelected {
rotatingView.stopRotating()
} else {
rotatingView.startRotating(duration: 3, clockwise: true)
}
sender.isSelected.toggle()
}
}