iOS - iPhone 4S 上的动画速度较慢(但在模拟器上很好)

发布于 2025-01-02 16:06:06 字数 863 浏览 0 评论 0原文

我使用以下代码对 UILabel 进行了子类化,该代码工作正常 - 但涉及子类的任何动画的运行速度都比正常的 UILabel 慢得多。我假设 Quartz 是罪魁祸首,但是我能做些什么来加快速度吗?

- (void)drawTextInRect:(CGRect)rect
{
    CGSize shadowOffset = self.shadowOffset;
    UIColor *textColor = self.textColor;

    // Establish the Quartz 2D drawing destination:
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 1);
    CGContextSetLineJoin(context, kCGLineJoinRound);

    // Draw the label’s outline:
    CGContextSetTextDrawingMode(context, kCGTextStroke);
    self.textColor = [UIColor whiteColor];
    [super drawTextInRect:rect];

    // Draw the label:
    CGContextSetTextDrawingMode(context, kCGTextFill);
    self.textColor = [UIColor textColor];
    self.shadowOffset = CGSizeMake(0, 0);
    [super drawTextInRect:rect];

    self.shadowOffset = shadowOffset;
}

I have subclassed a UILabel with the following code, which works fine - but any animations involving the subclass runs a lot slower than normal UILabels. I'm assuming Quartz is the culprit, but is there anything I could do to speed things up a bit?

- (void)drawTextInRect:(CGRect)rect
{
    CGSize shadowOffset = self.shadowOffset;
    UIColor *textColor = self.textColor;

    // Establish the Quartz 2D drawing destination:
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 1);
    CGContextSetLineJoin(context, kCGLineJoinRound);

    // Draw the label’s outline:
    CGContextSetTextDrawingMode(context, kCGTextStroke);
    self.textColor = [UIColor whiteColor];
    [super drawTextInRect:rect];

    // Draw the label:
    CGContextSetTextDrawingMode(context, kCGTextFill);
    self.textColor = [UIColor textColor];
    self.shadowOffset = CGSizeMake(0, 0);
    [super drawTextInRect:rect];

    self.shadowOffset = shadowOffset;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谎言月老 2025-01-09 16:06:06

@MobileOverlord所说的当然适用,尤其是关于分析的部分。

我要指出的是,设置 shouldRasterize=YES 并不是一个包罗万象的解决方案(如果是这种情况,为什么 Apple 不将其设置为默认值?)。是的,它可以提高滚动性能,但它会以内存使用为代价,因为最终可能会在缓存中留下一堆大图像。

我相信(但必须检查以确保),它还会在创建时产生开销,包括离屏渲染通道以实际创建光栅化副本。根据层的使用方式,这实际上可能会损害性能。

另一个需要考虑的因素是您的观点是否具有透明度。如果您可以向框架保证您的视图是不透明的(参见 setOpaque/isOpaque),他们可以通过不考虑与 alpha 通道等相关的所有复杂性来优化渲染。类似的考虑也适用于 CALayer。

最后,在您展示的代码块之外,您是否对支持层做了任何偷偷摸摸的事情(例如设置阴影或角半径)?这也是扼杀动画性能的一种快速方法。

What @MobileOverlord said is certainly applicable, especially the parts about about profiling.

I will note that setting shouldRasterize=YES is not a catch-all solution (why wouldn't Apple have set it on as default if that were the case?). Yes, it can improve scrolling performance, but it can do so at the expense of memory use since you can end up with a bunch of large images sitting around in cache.

It also incurs overhead at the time of creation, I believe (but would have to check to be sure) including an off-screen rendering pass to actually create the rasterized copy. Depending on how the layer is used, this could actually hurt performance.

An additional factor to consider is whether your view has any transparency. If you can guarantee to the frameworks that your view is opaque (cf. setOpaque/isOpaque), they can optimize rendering by not considering all the complexities associated with alpha channels, etc. Similar considerations apply to CALayer.

Finally, outside the block of code you showed, did you do anything sneaky to the backing layer (e.g. set a shadow or corner radius)? That's a quick way to kill performance on animation too.

開玄 2025-01-09 16:06:06

完成标签绘制后,您可以在其图层上调用 shouldRasterize ,它应该会加快动画速度。

shouldRasterize 一个布尔值,指示图层是否渲染
作为合成之前的位图。可动画

@property BOOL shouldRasterize 讨论何时设置 this 的值
属性为 YES,图层在其本地渲染为位图
坐标空间,然后与任何其他空间合成到目的地
内容。阴影效果和滤镜属性中的任何滤镜都是
光栅化并包含在位图中。然而,目前的不透明度
该图层未栅格化。如果光栅化位图需要缩放
在合成过程中, minificationFilter 中的过滤器和
magnificationFilter 属性根据需要应用。

当该属性值为NO时,图层被合成
尽可能直接到达目的地。该层可能仍
如果某些特征在合成之前被光栅化
合成模型(例如包含过滤器)需要它。

该属性的默认值为NO。

来自 CALayer 类参考

模拟器总是会给您带来比设备更好的结果,因为它能够使用系统的全部处理能力和内存。通过这种方式,您通常会得到有缺陷的结果。每当您结合 CoreAnimation 进行 CoreGraphics 绘图时,在真实设备上测试结果非常重要。

为此,您可以尝试在 Instruments Core Animation Tool 中运行您的应用程序,以尝试找到罪魁祸首。查看我的教程。

Instruments – 优化核心动画

After you are finished drawing your label you can call shouldRasterize on it's layer and it should speed up your animation.

shouldRasterize A Boolean that indicates whether the layer is rendered
as a bitmap before compositing. Animatable

@property BOOL shouldRasterize Discussion When the value of this
property is YES, the layer is rendered as a bitmap in its local
coordinate space and then composited to the destination with any other
content. Shadow effects and any filters in the filters property are
rasterized and included in the bitmap. However, the current opacity of
the layer is not rasterized. If the rasterized bitmap requires scaling
during compositing, the filters in the minificationFilter and
magnificationFilter properties are applied as needed.

When the value of this property is NO, the layer is composited
directly into the destination whenever possible. The layer may still
be rasterized prior to compositing if certain features of the
compositing model (such as the inclusion of filters) require it.

The default value of this property is NO.

From CALayer Class Reference

The simulator is always going to give you way better results than a device will because it is able to use the full processing power and memory of your system. You'll usually get flawed results this way. Whenever you are doing CoreGraphics drawing in conjunction with CoreAnimation it is important to test the results on a real device.

For this you can try to run your app in Instruments Core Animation Tool to try to find culprits. Check out my tutorial on it.

Instruments – Optimizing Core Animation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文