2016-06-22 2 views
1

Я пытаюсь добавить CAShapelayer один раз каждые 20 мс с заданными координатами x и y. Я бы хотел, чтобы форма исчезла более секунды (например, индикатор). Функция, которую я создал, работает, форма создается в правильном месте и исчезает. Но я получаю дополнительные фигуры, оставшиеся за решеткой.CAShapelayer Duplicates

func shadowBall (x: CGFloat, y: CGFloat){ 

    let xpos : CGFloat = ((self.frame.width/2) + x) 
    let ypos : CGFloat = ((self.frame.height/2) + y) 

    let shadowBall = CAShapeLayer() 
    let shadowBalllRadius :CGFloat = 4 
    let shadowBallPath : UIBezierPath = UIBezierPath(ovalInRect: CGRect(x: xpos, y: ypos, width: CGFloat(shadowBalllRadius*2), height: CGFloat(shadowBalllRadius*2))) 

    shadowBall.path = shadowBallPath.CGPath 
    shadowBall.fillColor = UIColor.clearColor().CGColor 
    shadowBall.strokeColor = UIColor.whiteColor().CGColor 
    shadowBall.lineWidth = 0.5 

    let animation: CABasicAnimation = CABasicAnimation(keyPath: "strokeColor") 
    animation.fromValue = UIColor.whiteColor().CGColor 
    animation.toValue = UIColor.clearColor().CGColor 
    animation.duration = 1.0; 
    animation.repeatCount = 0; 
    animation.removedOnCompletion = true 
    animation.additive = false 

    self.layer.addSublayer(shadowBall) 
    shadowBall.addAnimation(animation, forKey: "strokeColor") 

} 
+0

Unrelated, но я нахожу «каждые 20мс», чтобы быть любопытно близко (но не равно) максимальная частота кадров 60 кадров в секунду. Вы используете для этого 'NSTimer'? Почему бы не использовать «CADisplayLink», который по существу является таймером, оптимизированным для обновлений фреймов? – Rob

+1

У меня есть устройство BLE с частотой обновления 50 Гц ... следовательно, 20 мс – duck1970

ответ

0

Проблема заключается в том, что, когда анимация заканчивается, он восстанавливает strokeColor к первоначальному цвету. Вы действительно должны установить strokeColor исходного слоя формы clearColor(), таким образом, когда вы закончите анимацию с whiteColor() до clearColor(), она останется на уровне clearColor().

Вы также можете установить слой fillMode в kCAFillModeForwards и установить removedOnCompletion в false и что будет иметь слой сохранить свой «конец анимации» состояние. Но я лично просто установил strokeColor, как описано выше, так как использование removedOnCompletiontrue мешает animationDidStop (см. Ниже).


Кроме того, я мог бы предположить, что вы также удалить слой, как только это сделано с анимацией, так что не не будет продолжать потреблять память, хотя это уже не видно.

func shadowBall (x: CGFloat, y: CGFloat) { 
    let xpos: CGFloat = ((self.frame.width/2) + x) 
    let ypos: CGFloat = ((self.frame.height/2) + y) 

    let shadowBall = CAShapeLayer() 
    let shadowBalllRadius: CGFloat = 4 
    let shadowBallPath = UIBezierPath(ovalInRect: CGRect(x: xpos, y: ypos, width: CGFloat(shadowBalllRadius*2), height: CGFloat(shadowBalllRadius*2))) 

    shadowBall.path = shadowBallPath.CGPath 
    shadowBall.fillColor = UIColor.clearColor().CGColor 
    shadowBall.strokeColor = UIColor.clearColor().CGColor 
    shadowBall.lineWidth = 0.1 

    let animation = CABasicAnimation(keyPath: "strokeColor") 
    animation.fromValue = UIColor.whiteColor().CGColor 
    animation.toValue = UIColor.clearColor().CGColor 
    animation.duration = 1.0 
    animation.repeatCount = 0 
    animation.removedOnCompletion = true 
    animation.additive = false 

    animation.delegate = self 
    animation.setValue(shadowBall, forKey: "animationLayer") 

    self.layer.addSublayer(shadowBall) 
    shadowBall.addAnimation(animation, forKey: "strokeColor") 
} 

override func animationDidStop(anim: CAAnimation, finished flag: Bool) { 
    if let layer = anim.valueForKey("animationLayer") as? CALayer { 
     layer.removeFromSuperlayer() 
    } 
} 

См How to remove a CALayer-object from animationDidStop?

+0

Блестяще и просто, спасибо за быстрый ответ. Некоторое время я искал эту проблему ... – duck1970