【问题标题】:Animations are not being killed on backgroundView of the UITableViewUITableView 的 backgroundView 上的动画没有被杀死
【发布时间】:2016-10-26 11:12:00
【问题描述】:

更新:

  1. 我有一个从 Web 服务加载数据的 UITableView。
  2. 在它加载数据时,我将它的 backgroundView 设置为 UIAnyCustomView(UIView 的子类),我以编程方式对其进行绘制并为其设置动画。
  3. 收到来自网络服务的数据后,我将 UITableView 的 backgroundView 设置为 nil,因为它是可选的,我认为应该自动删除动画,但事实并非如此。

我的问题:为什么?

原始问题(为澄清而更新)

我收到了一些关于我的某个应用的电池使用情况反馈。我使用 xCode 仪器监控电池使用情况并发现了问题。我正在静态设置 UITableView/UICollectionView 的 backgroundView,它永远调用动画(我们称之为 UICustomeActivityIndi​​cator):

fileprivate func rotateLoadingView() {
    UIView.animate(withDuration: 0.5, delay: 0.0, options: [.curveLinear], animations: {
        self.innerCircleView.transform = self.innerCircleView.transform.rotated(by: CGFloat(M_PI_2))
    }) { result in
        if !self.isHidden {
            self.rotateLoadingView()
        }
    }
}

然后,当内容被加载时,我通过将其设置为 nil 来清除 backgroundView:

// collectionView.backgroundView = nil
tableView.backgroundView = nil

但即使我正在清除 backgroundView,动画仍在继续,并且正在消耗大量电池(在将应用程序发送到后台时也是如此)。

我的问题;这种行为是正常的还是backgroundView UITableView/UICollectionView的bug,设置为nil时应该自动清除?

【问题讨论】:

  • 你在控制器的任何地方都在做activityIndicator.hidden = true吗?为什么你认为将backgroundView 设置为nil 会影响activityView
  • 是的,我确实设置了 activityIndi​​cator.hidden = true。当我将 backgroundView 设置为 nil 时,为什么它不影响 activityView?系统应该自动删除它的动画,对吧?

标签: ios swift uitableview uicollectionview uiviewanimation


【解决方案1】:

您错误地认为从层次结构中删除视图会导致系统取消动画。可以将视图添加到父视图中,也可以不添加,但在任何情况下,您都可以在其上运行动画,除非对象被完全释放。因此,由于您在控制器中强烈引用 indicatorView,它仍然存在,没有理由删除您的动画。

我建议避免使用递归方法。您可以通过自定义活动指示器中的两种方法来实现您需要的结果:

func startAnimation() {
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.fromValue = 0.0
    rotateAnimation.toValue = CGFloat(M_PI * 2.0)
    rotateAnimation.duration = 1
    rotateAnimation.repeatCount = .infinity

    layer.add(rotateAnimation, forKey: nil)
}

func stopRotation() {
    layer.removeAllAnimations()
}

现在,只要您需要在控制器中调用 startstop,就不会遇到您所描述的任何问题。

【讨论】:

  • 请不要超出问题范围。即使在递归调用动画时我的方法是错误的,当我将 backgroundView 设置为 nil 时,系统应该自动删除它的动画,对吗?我想用这个问题来澄清这个案例。
  • 您的问题并未阐明您的活动指示器与 backgroundView 的实际关系。它是 backgroundView 的子视图还是什么?
  • @alexburtnik 这是 UIView 的扩展,它具有任何动画(无论是像我的还是你的那样递归地动画)。当我将 backgroundView 设置为 nil 时,它应该被清除,对吧?为什么它继续在背景中播放动画?
  • 不,不应该被清除。 IndicatorView 仍然存在,并且无论您对 backgroundView 做什么,它的递归方法仍在运行。
  • @alexburtnik 对此的任何解释(参考或澄清原因?)将不胜感激。
【解决方案2】:

移除视图不会移除动画,因为动画是在 UIView 层中添加的。将视图设置为 nil 不会更改图层属性。删除视图只删除可见部分而不是图层属性。这就是动画在后台运行的原因。通过调用 removeAllAnimations() 删除视图层中的所有动画

view.layer.removeAllAnimations()

【讨论】:

  • 动画被添加到视图层,通过移除视图无法移除动画。如果你想停止,你必须从图层中删除动画。
  • 我的意见:当我们将可选的backgroundView设置为nil时,它应该被移除。所以不存在的视图不能动画,对吧?
  • 不,这就是layer和UIView的区别,这里我们将动画设置到layer而不是view。通过删除视图,您只删除了可见部分,而不是应该单独处理的图层属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多