为什么CATransaction setCompletionBlock在动画持续时间后被延迟

时间:2015-01-13 15:50:06

标签: ios animation swift core-animation

我尝试用CATransaction练习CABasicAnimationCAShapeLayer,我按照自己的意愿完美地完成了动画制作工作,但动画完成后的块并未立即调用动画结束了。

以下是我使用的关键代码:

func startAnimation(){
    CATransaction.begin()
    CATransaction.setAnimationDuration(10.0)
    let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
    pathAnimation.duration = 10.0
    pathAnimation.fromValue = 0.0 as NSNumber
    pathAnimation.toValue = 1.0 as NSNumber

    CATransaction.setCompletionBlock { () -> Void in
        NSLog("finished")
    }
    pathLayer.addAnimation(pathAnimation, forKey: "strokeEnd")
    self.layer.addSublayer(pathLayer)
    CATransaction.commit()
    NSLog("start")
}

输出

2 NSLog的输出如下所示:

2015-01-14 00:30:05.549 QuartzCorePlayground[47369:2769473] start
2015-01-14 00:30:22.004 QuartzCorePlayground[47369:2769473] finished

问题得到答案

  

为什么finished总是在动画结束后大约6.5秒打印出来?我的代码出了什么问题?

ANSWER

原因是,正如评论中所提到的,它似乎是Xcode游戏中的一个错误,当我把代码放在真实项目中时,它就像我对CoreAnimation的理解一样。


完整的playgroud代码

以下是我在Xcode游乐场中运行的完整代码(您需要检查Xcode中的 Run in Full Simulator 选项)

// Playground - noun: a place where people can play

import UIKit
import XCPlayground

func radians(degree : CGFloat) -> CGFloat{
    return CGFloat((Double(degree) / 180) * M_PI)
}

class TimerShapeView : UIView {

    var pathLayer = CAShapeLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)

        let innerSize : CGFloat = 20
        var squareRectSize = min(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))
        var squareRect = CGRectInset(self.bounds, (CGRectGetWidth(self.bounds) - squareRectSize)/2 + innerSize, (CGRectGetHeight(self.bounds) - squareRectSize)/2 + innerSize)

        let workoutPath = UIBezierPath()
        workoutPath.addArcWithCenter(CGPoint(x: CGRectGetMidX(squareRect), y: CGRectGetMidY(squareRect)), radius: CGRectGetWidth(squareRect)/2, startAngle: radians(90), endAngle: radians(360), clockwise: true)

        pathLayer.frame = self.bounds
        pathLayer.path = workoutPath.CGPath
        pathLayer.lineWidth = 2.0
        pathLayer.strokeColor = UIColor.purpleColor().CGColor
        pathLayer.geometryFlipped = true
        pathLayer.fillColor = nil
        pathLayer.lineJoin = kCALineJoinBevel

        self.layer.addSublayer(pathLayer)

        self.backgroundColor = UIColor.greenColor().colorWithAlphaComponent(0.1)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func startAnimation(){
        CATransaction.begin()
        CATransaction.setAnimationDuration(10.0)
        let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
        pathAnimation.duration = 10.0
        pathAnimation.fromValue = 0.0 as NSNumber
        pathAnimation.toValue = 1.0 as NSNumber

        CATransaction.setCompletionBlock { () -> Void in
            NSLog("finished")
        }
        pathLayer.addAnimation(pathAnimation, forKey: "strokeEnd")
        self.layer.addSublayer(pathLayer)
        CATransaction.commit()
        NSLog("start")
    }

}

var shapeTimerView = TimerShapeView(frame: CGRect(x: 0, y: 0, width: 320, height: 220))
XCPShowView("newTimerView", shapeTimerView)

shapeTimerView.startAnimation()

0 个答案:

没有答案