UIView setCenter 的替代品

Posted

技术标签:

【中文标题】UIView setCenter 的替代品【英文标题】:alternative to UIView setCenter 【发布时间】:2014-04-18 03:06:30 【问题描述】:

我的应用程序是一款游戏,它包含一个 CADisplayLink 计时器,该计时器调用一个函数,该函数指示每帧屏幕上的各种对象对 UIView setCenter: 进行大约 20 次调用。

时间分析,这约占游戏中所有活动的 30%,并大大降低了旧设备(低于第 5 代 ipod touch 或 iphone)的性能。

我可以使用任何轻量级、低开销的替代方案来每帧在屏幕上移动对象(特别是 UIViews)吗?

编辑:

澄清一下,这些UIViewscenter 属性必须在每一帧中设置。我的游戏中有许多代表地面的图块。它们在屏幕上滑动,只是被新的瓷砖取代。在摆弄代码几个小时以将UIViews 更改为CAlayers 之后,我让它完全没有性能提升。肯定有更好的方法来做到这一点。

一些代码可以大致了解正在发生的事情:

for(Object* o in gameController.entities)
    [o step:curTimeMS];

gameController,正如人们所想的那样,是一个负责主要游戏功能的类。它包括其实体列表,即屏幕上的所有对象。每个实体上的 step 方法是一个虚函数,因此它特定于每个实体 - curTimeMS 变量只是一个时间戳,因此对象可以计算其增量位置。实质上,每个实体每帧都会更新其layer.position 属性,并以适当的速度在屏幕上移动。

【问题讨论】:

既然是游戏,你检查过SpriteKit了吗?这是一个很棒的框架,有趣且易于使用。 @Winston 同意,但我认为他想在早期的系统上运行。 是的,没错,因为他在他的问题上提到了第 5 代 ipod touch 或 iPhone。 @Winston 正如马特所说,我确实想支持早期的系统,但 SpriteKit 似乎是未来的好方法,感谢您的建议:) 你会玩得很开心的。 【参考方案1】:

我会推荐 SpriteKit。这是一个very powerful game / 2d animation framework created by apple.。 Cocos2D is also a very powerful framework of similar type. 你可以直接从XC创建一个新的SpriteKit游戏

如果您想留在家里只带UIKit 的东西,请查看UIView block based animations。这是它的要点。

[UIView animateWithDuration:numberOfSecondsTakenToAnimate animations: ^
    // do you animation here. i.e.: move view frame, adjust color.

 completions: ^(BOOL complete) 
    // when the animation is complete, code in this block is executed.

];

我只记得Core Graphics。它与UIViews 一起使用来创建简单的2d 图形,并且非常 强大且非常 快速。这是其中的要点。

CGContextRef cntxt = UIGraphicsGetCurrentContext();
CGContextBeginPath(cntxt);

CGContextMoveToPoint(cntxt, <x>, <y>);
CGContextAddLineToPoint(cntxt, <x>, <y>);
CGContextClosePath(cntxt);

[[UIColor <color>] setFill];
[[UIColor <color>] setStroke];

CGContextDrawPath(cntxt, kCGPathFillStroke);

注意:中的东西是你指定的变量/值。

如果你想全力以赴,take the time to learn Open GL。请注意,我听说这非常难学。

【讨论】:

感谢您的回答。但是,正如之前的 cmets 中所讨论的,我故意不使用 SpriteKit 以支持早期的 iO​​S 版本和设备。 我知道UIViewanimateWithDuration: animations:,但我没有考虑将它作为框架调整的基础。您认为这会带来性能提升吗? @Fitzy 不确定,但它看起来非常流畅。如果您正在寻找性能,还可以查看我对 Core Graphics 的编辑。我对这个框架有个人经验,我可以证明它的性能 我刚刚看到你的编辑,似乎有些人建议使用它,而我在这个网站上看到的其他答案明确表示 Core Graphics 和 UIKit 之间的差异可以忽略不计,因为 UIKit 的 @987654334 @ 是 CALayer 的一个非常轻量级的包装器 好吧,我相信你。我会研究选项。至于 OpenGL,我对它有一定的经验,并且可以确认它对于这个小 2D 游戏来说绝对是矫枉过正。 :)【参考方案2】:

如果您需要性能,请不要使用UIView。它的设计初衷不是为了快速。

相反,有一个 UIView 占据整个屏幕,在一个视图内有一堆 CALayer 对象。移动图层。

CALayer 通过直接与 GPU 对话来工作,因此速度非常快。也许甚至比 OpenGL 还要快。 UIView 在内部使用 CALayer,因此它们的行为大致相同。唯一真正的区别是对CALayer 位置的任何更改将默认设置为动画。您可以轻松关闭动画,但在游戏中您可能需要动画。

当然,您的另一个选择是使用 OpenGL。但这还有很多工作要做。

编辑:这里是一些用于正确更改图层位置的示例代码:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html#//apple_ref/doc/uid/TP40004514-CH3-SW8

【讨论】:

我在其他 SO 答案中读到 CALayerUIView 没有任何显着的性能差异。所以值得改变我的代码来支持CALayers而不是UIViews?我确实有使用 OpenGL 的经验,但是由于这个项目即将完成,最好不要重写大量代码。 我可以在重组一堆代码后确认CALayer 对性能没有任何改进,并且在时间配置文件中进行测试时,所有相同的底层函数都会被调用。 @Fitzy 所以您发现将图层从屏幕上的一个位置移动到另一个位置很慢?而你只有20层?这根本不是我的经验,我的代码可以一次移动 200,000 层或更多层而没有性能问题。您可以发布您正在使用的代码吗? @Fitzy 我更新了我的答案以显示 Apple 如何建议您应该沿特定路径移动图层的位置。请注意,他们不使用setPosition:。但是,我个人对setPosition: 的使用要求很高,没有性能问题。我想再看看你的代码。

以上是关于UIView setCenter 的替代品的主要内容,如果未能解决你的问题,请参考以下文章

自定义默认 UIAlertView

Swift - 使用 UiView 的 iCarousal

两个 UIView,一个 UIViewController(在一个 UINavigationController 中)

在隐藏的 UIView 中接收触摸事件?

使 UIView 或 CALayer 变暗的最快方法(性能方面)

我可以在笔尖和编程中定义 UIView 吗?