目前我正在通过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:
现在我在当前的实现中面临一个大问题,因为我依赖于AutoLayout。什么是解决iOS 7麻烦的最简单的解决方案?
答案 0 :(得分:5)
虽然你说他们做同样的事情是正确的,但它并不容易 - 在整个地方都有矩阵乘法。 More on that can be found here。
奇怪的是,如果你这样做,它会影响你的表现 - 但我猜你的布局很复杂,因此重新渲染需要花费很多时间;我实际上遇到了像一周前一样的问题,所以这里有什么帮助我:
此外,您可以尝试在异步调用中分配该转换,看看是否有帮助:
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属性,而不是框架。它可以节省您再次定义高度/宽度的需要,并让您更清楚地了解您的意图。