为什么没有自定义的CALayer的抽签方法早叫什么名字?

问题描述 投票:1回答:2

问题

我触发使用定时器选择UIViews的随机动画。所有动画工作打算,但在其中一种的CALayer的抽签方法计时器选择的退出后调用。

详细说明

为了清晰和简单起见,让我schematise执行的操作。

Cycle

所有的动画我到目前为止创建工作像预期一样:他们是在现有的子视图/子层或添加到选定的视图层次换新CABasicAnimations的组合。它们被编码为一个UIView的扩展,让他们可以在任何意见被调用,视图或视图控制器的看法是好了,除此之外的所有工作无关。

我确实创造了一个自定义的CALayer类包括在一个CALayer的绘画图案。在该自定义类的扩展,有动画那些图案的方法(见下文称为代码)。因此,所有的一切,当我到达步骤/方法animate selected view并运行这个特殊的动画,这里是应该发生的事情:

  • 一个名为animatePattern方法被调用
  • 这种方法增加了定制的CALayer类到所选择的视图,然后调用该层的动画延伸

问题:如果与所有其他的动画,所有的附图之前animate selected view步骤/方法的出口进行的,在该特定情况下,所述定制的CALayer类拉伸方法在performAnimation方法的出口处,之后调用这反过来导致动画的崩溃。

我要补充一点,我试图在一个单独的和简化的操场定制CALayer的类动画和它运作良好,(我在UIViewController的UIView方法定制层添加到viewDidLoad,然后我打电话在UIViewController的viewDidAppear方法层动画。)

编码

  • 通过animate selected view步骤/方法调用的方法: func animatePattern(for duration: TimeInterval = 1) { let patternLayer = PatternLayer(effectType: .dark) patternLayer.frame = self.bounds self.layer.addSublayer(patternLayer) patternLayer.play(for: duration) }

(请注意,这种方法是在一个UIView延伸,因此这里self表示在其上的动画被称为的UIView)

  • 简化的自定义的CALayer类: override var bounds: CGRect { didSet { self.setNeedsDisplay() } // Initializers override init() { super.init() self.setNeedsDisplay() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } init(effectType: EffectType){ super.init() // sets various properties self.setNeedsDisplay() } // Drawing override func draw(in ctx: CGContext) { super.draw(in: ctx) guard self.frame != CGRect.zero else { return } self.masksToBounds = true // do the drawings }
  • 自定义的CALayer类的动画扩展: func play(for duration: Double, removeAfterCompletion: RemoveAfterCompletion = .no) { guard self.bounds != CGRect.zero else { print("Cannot animate nil layer") return } CATransaction.begin() CATransaction.setCompletionBlock { if removeAfterCompletion.removeStatus { if case RemoveAfterCompletion.yes = removeAfterCompletion { self.fadeOutDuration = 0.0 } self.fadeToDisappear(duration: &self.fadeOutDuration) } } // perform animations CATransaction.commit() }

尝试至今

我曾试图强行通过在代码的不同位置插入setNeedsDisplay / setNeedsLayout绘制层,但它不工作:调试draw方法退出后不断达到定制的CALayer类的performAnimation方法,而应该叫当层的帧被在animatePattern方法改性。我必须错过的东西很明显,但我目前手忙脚乱,我会很感激一双崭新的眼睛就可以了。

预先感谢您抽出宝贵的时间来考虑这个问题!最好,

ios swift animation timer draw
2个回答
0
投票

您覆盖抽奖(_上下文)作为UIView的可能的CALayer的委托。

 UIView: {

    var patternLayer :  PatternLayer

     func animatePattern(for duration: TimeInterval = 1) {

      patternLayer      = PatternLayer(effectType: .dark)
       patternLayer.frame      = self.bounds
       self.layer.addSublayer(patternLayer)
     }

      func draw(_ layer: CALayer, in ctx: CGContext){
        layer.draw(ctx)
         if  NECESSARY { patternLayer.play(for: duration)}

        }

      }

-1
投票

由于它是经常有这种情况,当你花时间去您的问题写下来,新的理念开始流行起来。事实上,我记得self.setNeedsDisplay()通知该层需要(重新)绘制的,但它不(重新)绘制一次系统:它会在下一次刷新期间进行。这似乎那么的刷新周期为特定的动画结束后发生。为了克服这个问题,我首先通过调用display方法,而不是增加了一个呼吁displayIfNeeded方法后右边的patternLayer边界被设置为,和它的工作,但鉴于@马特评论,我改变了解决方案。它的工作原理也是如此。

func animatePattern(for duration: TimeInterval = 1) {

let patternLayer        = PatternLayer(effectType: .dark)
patternLayer.frame      = self.bounds
self.layer.addSublayer(patternLayer)

// asks the system to draw the layer now
patternLayer.displayIfNeeded()

patternLayer.play(for: duration)

}

再次,应该有人想出另一种更优雅的解决方案/解释,请不要犹豫分享!

© www.soinside.com 2019 - 2024. All rights reserved.