Xcode-Swift 中的呼吸动画,同时应用响应

Breathing animation in Xcode-Swift while app being responsive

我正在尝试循环播放星星 "breathe" 的图像。变大,然后变小,然后不断重复。我希望在我的应用程序仍然 运行 并且响应迅速时继续进行。当我转到我的应用程序中的另一个视图时,我希望动画停止。

这是我得到的

    override func viewDidLoad() {
    super.viewDidLoad()

    DispatchQueue.main.async {
            self.animateStars()
    }
}

func animateStars() {
  UIView.animate(withDuration: 4, animations : {
        self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5)

    }) { finished in
        NSLog("Star is big. Finished = \(finished)")
    }

    UIView.animate(withDuration: 4, animations : {
        self.star.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)

    }) { finished in
        NSLog("Star is small. Finished = \(finished)")
    }
}

这并不难循环。而且我不知道如何在没有它的情况下使它循环 运行 就像在后台发疯一样,当用户单击带有 segue 的按钮以转到另一个视图时。

我在 Objective C 中找到了一个解决方案,但我似乎无法理解如何将其转换为 Swift 3.0。此处示例:

 [UIView animateWithDuration:1
                  delay:0
                options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
             animations:^{
                 yourView.transform = CGAffineTransformMakeScale(1.5, 1.5);
             }
             completion:nil];

感谢您的宝贵时间和建议! //西蒙

尝试添加保存布尔值的变量,该值表明它是否需要动画。并在用户点击按钮转到下一个屏幕时更改它。

像这样:

var animate = true

override func viewDidLoad() {
   super.viewDidLoad()

   self.animateStars()
}

func animateStars() {
  while animate == true   {
    // breathing animation
  }
}

@IBAction func buttonPressed(_ sender: UIButton) {
   animate = false

   // perform your segue
}

如果您想在用户返回此屏幕时再次将其设置为动画,请将 self.animateStars() 置于 viewWillAppear 方法中。

您发布的 Objective-C 重复动画代码的 Swift 版本为:

UIView.animate(withDuration: 1.0,
               delay: 0,
               options: [.autoreverse, .repeat, .allowUserInteraction],
               animations: {
                self.star.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
},
               completion: nil

)

(在Swift中,大多数option flag参数如那个动画代码中的options参数都是OptionSet类型的,是支持Swift的位标志Set 语法,所以你在方括号中列出你想要的选项,用逗号分隔。

请注意,@TungFam 的解决方案不会像写的那样工作,但如果您使用完成块来检查 animate 布尔值并在为真时重新调用动画方法,则可以使用该方法。

编辑:

如果你想停止动画,使用

self.star.layer.removeAllAnimations()
self.star.layer.transform = CGAffineTransform.identity

编辑#2:

如果你希望能够随意开始和停止一个动画,你可以使用这样的代码:

func animateView(_ view: UIView, animate: Bool) {
  if animate {
    UIView.animate(withDuration: 1.0,
                   delay: 0,
                   options: [.autoreverse, .repeat, .allowUserInteraction],
                   animations: {
                    view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
    },
                   completion: nil

    )
  } else {
    self.button.layer.removeAllAnimations()
    UIView.animate(withDuration: 1.0,
                   delay: 0,
                   options: [.curveEaseOut, .beginFromCurrentState, .allowUserInteraction],
                   animations: {
                    view.transform = CGAffineTransform.identity
    },
                   completion: nil

    )
  }
}

当动画停止时,该代码将使视图平滑地动画回到正常大小。它还将 .allowUserInteraction 标志添加到动画中,以防您正在设置动画的视图是您希望能够在其大小发生变化时点击的按钮。

根据@DuncanC 的一些见解,我能够很好地工作。现在,当我转到另一个视图时动画停止,当我返回原始视图时动画继续。

代码如下所示:

class MainViewController: UIViewController {

@IBOutlet weak var star: UIImageView!

var queue = DispatchQueue.main

  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.star.layer.removeAllAnimations()
    self.star.transform = CGAffineTransform.identity

    queue.async {
        self.animateStars()
    }
}
    @IBAction func someAction(_ sender: Any) {
    performSegue(withIdentifier: "someSegue", sender: self)
    }

    func animateStars() {
    UIView.animate(withDuration: 1,
                   delay: 0,
                   options:[.autoreverse, .repeat],
                   animations : {
                    self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5)})
    { finished in
        UIView.animate(withDuration: 1.0,
                       delay: 0,
                       options: [.curveEaseOut, .beginFromCurrentState],
                       animations: {
                        self.star.transform = CGAffineTransform.identity
        },
                       completion: nil
        )
    }
    UIView.animate(withDuration: 1, 
                   delay: 0, 
                   options: [.autoreverse, .repeat], 
                   animations: { self.star.transform = CGAffineTransform(scaleX: 2.5, y: 2.5) })
}
}

我对编程还是很陌生,正在上学,到目前为止我还没有学到那么多关于测试的知识。因此,我还没有测试它是否存在内存泄漏和诸如此类的问题。但是代码有效,这意味着我暂时很高兴。

谢谢大家的帮助!如果您认为可以改进代码,请提出建议。 :)

//西蒙