【问题标题】:When creating an animation, why do you message to the UIView class property?创建动画时,为什么要向 UIView 类属性发送消息?
【发布时间】:2016-12-29 18:14:26
【问题描述】:

我正在关注this 教程。代码 sn-p 可以在here 找到。在某些动画中,动画直接发送到UIView。就像下面的代码 sn-p。

问题1:这个UIView是什么类的什么属性?还是我们正在向屏幕上所有内容的 UIView 发送消息,执行代码块中的内容?我只是想了解我们在此处发送的消息是哪个属性...

protocol Flashable {}

extension Flashable where Self: UIView {
    func flash() {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
            self.alpha = 1.0
        }) { (animationComplete) in
            if animationComplete == true {
                UIView.animate(withDuration: 0.3, delay: 2.0, options: .curveEaseOut, animations: {
                    self.alpha = 0.0
                    }, completion: nil)
            }
        }
    }
}

^^^我没有得到UIView.animate 部分。 ^^^

对于某些人来说,它不会直接发送给UIView

extension Jitterable where Self: UIView {
    func jitter() {
        let animation = CABasicAnimation(keyPath: "position")
        animation.duration = 0.05
        animation.repeatCount = 5
        animation.autoreverses = true
        animation.fromValue = NSValue(cgPoint: CGPoint.init(x: self.center.x - 5.0, y: self.center.y))
        animation.toValue = NSValue(cgPoint: CGPoint.init(x: self.center.x + 5.0, y: self.center.y))
        layer.add(animation, forKey: "position")
    }
}

^^^上面的代码比较好理解^^^

但是,当您想同时调用它们时:

errorLabel.flash()
errorLabel.jitter()

问题2:两种动画的编写方式有什么区别?

【问题讨论】:

    标签: ios swift animation uiview


    【解决方案1】:

    动画块在所有视图中都是全局的。给定的动画块是免费的(并鼓励)同时为尽可能多的视图设置动画。所以这自然是一个“全局”函数,与任何特定视图无关。

    在面向对象编程中,通常将“全局”函数实现为某个相关类的静态/类方法。这改善了名称间距(有时还有其他好处,例如访问类数据)。这就是这里发生的一切。 UIView 是嵌套全局 animate(withDuration:...) 方法的方便且富有表现力的地方。但这些方法实际上只是全局函数。没有严格的规定,他们甚至必须为视图设置动画。

    在您的CABasicAnimation 代码中,还创建了一个隐式全局CATransaction,它包含所有当前动画。所以“更容易理解”的版本也更神奇一些,它对你隐藏了一些更复杂的部分(如果你不理解它可能会咬你)。 UIView 版本实际上更明确地说明了正在发生的事情,尤其是当您同时为多个事物制作动画时。这就是添加 UIView 包装器的原因之一,也是为什么它通常是动画视图的更好方法。

    【讨论】:

    • 谢谢 1. 所以理论上我们可以在ViewController 类上编写该全局函数并执行相同的操作,但是出于命名目的,它可能不是最佳选择? 2. 还创建了一个隐式全局 CATransaction,它封装了所有当前动画
    • 我相信你可以就将它附加到 UIViewController 提出一个体面的论据——毕竟有些人可能认为动画是 MVC 中“C”的一部分。但事实是,您可以制作动画的任何东西都是 UIView 或其子类之一,我认为动画是 MVC 中“V”的一部分。作为 Swift 3 的一部分,事物的命名朝着更加“面向动作”的方向迈出了一大步。也许从这些方面思考你可以在 Swift 出现之前很久就看到他们把它放在正确的位置。 :-)
    • UIViewController 会很尴尬,因为不需要存在视图控制器,但它可能已经存在。 CATransaction 将动画组合在一起。默认情况下,在同一事件循环中创建的所有动画都由隐式事务连接。 (显式事务由begin()commit() 管理。)这不是“一次运行一个动画sn-p”的问题。各种动画可能会交互(动画相同的属性)并且需要协调,并且必须协同工作以达到渲染目的。
    • 请记住,CoreAnimation 动画不只是一遍又一遍地调用setCenter:(这就是动画过去的工作方式,以及 UIKitDynamics 的工作方式)。动画被并行合成到图层中(通常是同时几帧),并且可以优化绘制操作。事务也会影响与隐式属性动画相关的“动作”系统。 (核心动画实际上非常复杂。)
    • 但是UIView.animate() 的重点是创建一个高级接口来平滑低级CA 方法和函数的各种复杂性。
    【解决方案2】:

    animate(withDuration:animations:completion:)函数是UIView的类型方法。

    这意味着您可以只调用类型UIView 上的函数,正如您在第一个代码sn-p 中看到的那样。你可以在Swift Language Guide中找到更多关于类型方法的信息

    此函数的第二个参数是您要执行的动画。这可以是单个视图上的动画(在本例中为 self)或任何其他数量的视图和动画。

    第二个版本的动画是CABasicAnimation。您设置动画,然后将其附加到您想要的特定图层。

    正如文档所说,CABasicAnimation 是

    为图层属性提供基本的单关键帧动画功能的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多