【问题标题】:CGAffineTransforms performance is really slow on iOS 7CGAffineTransforms 在 iOS 7 上的性能真的很慢
【发布时间】:2015-06-19 06:45:27
【问题描述】:

目前,我正在通过CGAffineTransform 创建一些转换和转换以用于平移视图,但由于iOS 7iPhone 4 下的转换性能,我遇到了麻烦。

我在 Istruments 中潜入并记录了这些东西,当我将变换应用到视图时,繁重的工作就完成了。

当前实施

func handlePan(recognizer : UIPanGestureRecognizer) {

        let drawerLocation = recognizer.locationInView(drawerView!)
        let locationInView = recognizer.locationInView(containerView!)
        let progressMax = containerView!.frame.height - 40 - 20

        if(recognizer.state == .Changed) {

            let offsetDrag = dragStartPosition.y - locationInView.y
            let progress = Float(offsetDrag / progressMax)

            if(offsetDrag >= 0) {

                let positionTransform = CGAffineTransformMakeTranslation(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(normalizedProgress)))
                viewWithTransform.transform = positionTransform // really bad performance here
            } else {
                // reset the transition
            }     
    }
}

iOS 7 的解决方法

func handlePan(recognizer : UIPanGestureRecognizer) {

        let drawerLocation = recognizer.locationInView(drawerView!)
        let locationInView = recognizer.locationInView(containerView!)
        let progressMax = containerView!.frame.height - 40 - 20

        if(recognizer.state == .Changed) {

            let offsetDrag = dragStartPosition.y - locationInView.y
            let progress = Float(offsetDrag / progressMax)

            if(offsetDrag >= 0) {
                if UIDevice.currentDevice().systemMajorVersion() > 7 {
                    let positionTransform = CGAffineTransformMakeTranslation(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(progress)))
                    viewWithTransform.transform = positionTransform // really bad performance here
                } else {
                    viewWithTransform.frame = CGRectMake(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(progress)), drawerView!.frame.size.width, drawerView!.frame.size.height); // works like a charm on iOS 7
                }

            } else {
                // reset the transition
            }     
    }
}

问题

为什么在 iOS 7 和我的带有CGAffineTransforms 的 iPhone 4 上性能如此糟糕?因为它对偏移量和解决方法中的帧设置做同样的事情。当我将UIView.animateWithDuration() 与变换一起使用时,它以60fps 的速度执行。在我的 iOS 7 基础上,我可以做什么不重写整个实现?

7 月 28 日更新 发现此问题可能涉及 AutoLayout。这是我当前调用的 TimeProfiler 堆栈:

现在我在当前的实现中面临一个大问题,因为我依赖于 AutoLayout。在 iOS 7 上解决这个麻烦的最简单的解决方案是什么?

【问题讨论】:

  • viewWithTransform.translate = 是自定义的还是应该是 viewWithTransform.transform = ?您是否(有意或无意)使用自动布局?您是否使用发布版本进行分析?

标签: ios objective-c swift core-animation cgaffinetransform


【解决方案1】:

虽然您说他们做同样的事情是对的,但在幕后,这并不容易 - 到处都有矩阵乘法。 More on that can be found here

奇怪的是,如果你这样做,它会影响你的性能 - 但我猜你的布局很复杂,所以重新渲染需要很多时间;实际上我一周前遇到了同样的问题,所以这对我有帮助:

  • 出于某种原因从该特定视图中删除 AutoLayout 有很大帮助
  • 当您不旋转/缩放视图时,应使用框架操作。当您使用它们时,它确实变得需要。
  • 移除阴影和半透明视图,尤其是当它们彼此后面有更多时,使用变换时真的会降低 FPS

另外,您可以尝试在异步调用中分配该转换,看看是否有帮助:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            // Transform view
        })
    })

如果你真的想要花哨,请使用POP Framework from Facebook。它非常适合你想要的东西,它允许你做一些花哨的东西,比如弹跳、弹性等。下面是你可以使用它的方法:

// Create spring animation (there are more types, if you want)
let animation = POPSpringAnimation(propertyNamed: kPOPViewCenter)

// Configure it properly
animation.autoreverses = false
animation.removedOnCompletion = true
animation.fromValue = view.center
animation.toValue = finalPositionPoint

// Add new animation to your view - animation key can be whatever you like, serves as reference
view.pop_addAnimation(animation, forKey: "YourAnimationKey")

编辑: 如果您只是移动视图,请使用 .center 属性,而不是框架。它节省了您再次定义高度/宽度的需要,并让您更清楚地了解您的意图。

【讨论】:

  • 我尝试了 dispatch_async 的东西。这真的很容易。我在 main_queue 并将转换发送到主队列上的下一个运行循环。听起来很简单。我从 facebook 知道 POP,但是否有可能在处理平移手势时使用它?我的意思是它被称为很多;)
  • 对于平移手势,我建议您为您的元素创建一个弹簧动画并设置属性removedOnCompletion = false。这样,即使在达到其“toValue”之后,它也将无限期地工作。平移时,只需更改 .toValue 即可再次开始动画。
  • @mariusLAN 您是否设法使用我的解决方案解决了您的问题?
  • 我今天会试试这个,抱歉当时正在度假:)
  • 我添加了一些新信息。我认为这是因为 AutoLayout :/
猜你喜欢
  • 2015-08-26
  • 2017-02-27
  • 1970-01-01
  • 2018-04-01
  • 2020-12-21
  • 2011-05-18
  • 2015-03-07
  • 2016-08-01
  • 1970-01-01
相关资源
最近更新 更多