问题
我有两个视图控制器,都包含在相应的UINavigationController和一个UITabBarController内.在其中一个视图控制器中,我正在创建一个气泡效果,我在屏幕上画出气泡并对其位置进行动画处理.当我使用标签栏移动到另一个视图控制器时,会出现此问题,这会导致cpu飙升并保持在100%,气泡继续动画.
我有两个视图控制器,都包含在相应的UINavigationController和一个UITabBarController内.在其中一个视图控制器中,我正在创建一个气泡效果,我在屏幕上画出气泡并对其位置进行动画处理.当我使用标签栏移动到另一个视图控制器时,会出现此问题,这会导致cpu飙升并保持在100%,气泡继续动画.
码
气泡的代码封装在UIView子类中.
- override func draw(_ rect: CGRect) {
- // spawn shapes
- for _ in 1 ... 10 { // spawn 75 shapes initially
- spawn()
- }
- }
drawRect方法重复地调用spawn函数以使用气泡填充视图.
- fileprivate func spawn() {
- let shape = CAShapeLayer()
- shape.opacity = 0.0
- // create an inital path at the starting position
- shape.path = UIBezierPath(arcCenter: CGPoint.zero,radius: 1,startAngle: 0,endAngle: 360 * (CGFloat.pi / 180),clockwise: true).cgPath
- shape.position = CGPoint.zero
- layer.addSublayer(shape)
- // add animation group
- CATransaction.begin()
- let radiusAnimation = CABasicAnimation(keyPath: "path")
- radiusAnimation.fromValue = shape.path
- radiusAnimation.toValue = UIBezierPath(arcCenter: center,radius: 100,clockwise: true).cgPath
- CATransaction.setCompletionBlock { [unowned self] in
- // remove the shape
- shape.removeFromSuperlayer()
- shape.removeAllAnimations()
- // spawn a new shape
- self.spawn()
- }
- let movementAnimation = CABasicAnimation(keyPath: "position")
- movementAnimation.fromValue = NSValue(cgPoint: CGPoint.zero)
- movementAnimation.toValue = NSValue(cgPoint: CGPoint(x: 100,y: 100))
- let animationGroup = CAAnimationGroup()
- animationGroup.animations = [radiusAnimation,movementAnimation]
- animationGroup.fillMode = kCAFillModeForwards
- animationGroup.isRemovedOnCompletion = false
- animationGroup.duration = 2.0
- shape.add(animationGroup,forKey: "bubble_spawn")
- CATransaction.commit()
- }
在CATransaction完成处理程序中,我从超级视图中删除形状并创建一个新的形状.对self.spawn()的函数调用似乎是问题
在viewDidDisappear的包含视图控制器我呼叫以下:
- func removeAllAnimationsFromLayer() {
- layer.sublayers?.forEach({ (layer) in
- layer.removeAllAnimations()
- layer.removeFromSuperlayer()
- })
- CATransaction.setCompletionBlock(nil)
- }
尝试从答案
我试图将removeAllAnimations函数添加到UITabBarControllerDelegate
- extension BaseViewController: UITabBarControllerDelegate {
- func tabBarController(_ tabBarController: UITabBarController,didSelect viewController: UIViewController) {
- bubblesView.removeAllAnimationsFromLayer()
- }
- }
解决方法
我想你的问题是,你只使用一个线程的所有东西.请随时随地发送影响您的GUI的所有内容,并将其显示给其他线程的新的spawn实例.看看怎么回事这样的事情
- fileprivate func spawn() {
- let shape = CAShapeLayer()
- shape.opacity = 0.0
- // create an inital path at the starting position
- shape.path = UIBezierPath(arcCenter: CGPoint.zero,clockwise: true).cgPath
- shape.position = CGPoint.zero
- // create an inital path at the starting position
- shape.path = UIBezierPath(arcCenter: startingPosition,radius: startRadius,startAngle: BubbleConstants.StartingAngle,endAngle: BubbleConstants.EndAngle,clockwise: true).cgPath
- shape.position = startingPosition
- // set the fill color
- shape.fillColor = UIColor.white.cgColor
- layer.addSublayer(shape)
- shape.opacity = Float(opacity)
- DispatchQueue.main.async {
- self.layer.addSublayer(shape)
- CATransaction.begin()
- }
- let radiusAnimation = CABasicAnimation(keyPath: "path")
- radiusAnimation.fromValue = shape.path
- radiusAnimation.toValue = UIBezierPath(arcCenter: center,radius: endRadius,clockwise: true).cgPath
- DispatchQueue.main.async { [unowned self] in
- CATransaction.setCompletionBlock { [unowned self] in
- // remove the shape
- DispatchQueue.main.async {
- shape.removeFromSuperlayer()
- shape.removeAllAnimations()
- }
- DispatchQueue.global(qos: .background).async {
- // spawn a new shape
- self.spawn()
- }
- }
- }
- let movementAnimation = CABasicAnimation(keyPath: "position")
- movementAnimation.fromValue = NSValue(cgPoint: startingPosition)
- movementAnimation.toValue = NSValue(cgPoint: destination)
- let animationGroup = CustomAnimationGroup()
- animationGroup.animations = [radiusAnimation,movementAnimation]
- animationGroup.fillMode = kCAFillModeForwards
- animationGroup.isRemovedOnCompletion = false
- animationGroup.duration = duration
- shape.add(animationGroup,forKey: "bubble_spawn")
- DispatchQueue.main.async {
- CATransaction.commit()
- }
- }