iOS 7上的CGAffineTransforms性能非常慢

时间:2015-06-19 06:45:28

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

目前我正在通过CGAffineTransform创建一些过渡并转换为平移视图,因为iOS 7和{{iPhone 4下的转换效果,我遇到了麻烦1}}。

我潜入了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和我的iPhone 4上使用CGAffineTransforms的性能如此糟糕?因为它使用偏移执行相同的操作,然后在变通方法中使用框架设置。当我使用UIView.animateWithDuration()进行转换时,它会以60fps的速度执行。在iOS 7的基础上,我怎能不重写整个实现?

7月28日更新 发现AutoLayout可能涉及此问题。这是我当前通话中的TimeProfiler Stack:

Time Profiler

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

1 个答案:

答案 0 :(得分:5)

虽然你说他们做同样的事情是正确的,但它并不容易 - 在整个地方都有矩阵乘法。 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属性,而不是框架。它可以节省您再次定义高度/宽度的需要,并让您更清楚地了解您的意图。