iOS 7上的CGAffineTransforms性能非常慢

iOS 7上的CGAffineTransforms性能非常慢,ios,objective-c,swift,core-animation,cgaffinetransform,Ios,Objective C,Swift,Core Animation,Cgaffinetransform,目前,我正在通过cAffineTransform为平移视图创建一些转换和变换,由于在iOS 7和iPhone4下的转换性能,我遇到了麻烦 我潜入地峡并记录了这些东西,当我将变换应用到视图时,繁重的工作就完成了 当前实施情况 func handlePan(recognizer : UIPanGestureRecognizer) { let drawerLocation = recognizer.locationInView(drawerView!) let loc

目前,我正在通过
cAffineTransform
为平移视图创建一些转换和变换,由于在
iOS 7
iPhone4
下的转换性能,我遇到了麻烦

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

当前实施情况

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
            }     
    }
}
问题

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和我的iPhone 4上的CGAffineTransforms的性能如此糟糕?因为它在解决方案中对偏移量和帧设置做相同的事情。当我将
UIView.animateWithDuration()与变换一起使用时,它以60帧/秒的速度执行。在iOS 7的基础上重写整个实现,我能做些什么

7月28日更新 发现自动布局可能与此问题有关。以下是我当前调用的TimeProfiler堆栈:


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

虽然他们做同样的事情是对的,但在幕后,这并不是那么容易——到处都是矩阵乘法

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

  • 出于某种原因从特定视图中删除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
        })
    })
如果你真的想变得花哨,那就用吧。它非常适合你想要的东西,它允许你做一些有趣的事情,如反弹、弹性等。以下是你如何使用它:

// 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属性,而不是框架。它省去了您再次定义高度/宽度的需要,并让您对自己的意图有了更清晰的了解。

查看WithTransform.translate=
自定义的还是应该是
查看WithTransform.transform=
?您是否(有意或无意)使用自动布局?您是否使用发布版本进行评测?我尝试了dispatch\u async方法。这真的很容易。我在主队列上,并将转换发送到主队列上的下一个runloop。听起来很简单。我从facebook上知道POP,但是有没有可能用它来做摇摄手势呢?我的意思是它叫很多;)对于平移手势,我建议您为元素创建一个spring动画,并将属性removedOnCompletion设置为false。这样,即使在达到其“价值”后,它也将不间断地工作。平移时,只需更改.toValue,它就会再次开始动画。@mariusLAN您是否使用我的解决方案解决了您的问题?我今天将尝试此操作,很抱歉我正在休假:)我添加了一些新信息。我认为这是因为自动布局:/