9

问题
我有两个视图控制器,它们都包含在各自UINavigationController的 s 和一个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, startAngle: 0, endAngle: 360 * (CGFloat.pi / 180), 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()
  }
}
4

2 回答 2

2

我认为你的问题是,你只使用一个线程来处理所有这些东西。请尝试将影响您的 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, radius: 1, startAngle: 0, endAngle: 360 * (CGFloat.pi / 180), 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, startAngle: BubbleConstants.StartingAngle, endAngle: BubbleConstants.EndAngle, 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()
    }
}
于 2016-09-27T12:33:12.980 回答
0

在 UITabBarController 中,关联的视图控制器具有平面结构。即每个选项卡中的视图控制器独立运行。

因此,func removeAllAnimationsFromLayer()必须在委托方法中添加

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController)

于 2016-09-27T11:22:15.947 回答