能否从UIView中复制CALayer?

6

这是我的设置:我有一个CALayer,想要在其上添加子层。我通过设置UILabel并将其图层添加到主图层来创建这些子层。当然,这会在后台留下庞大的UILabel对象。是否可能从UIView中获取具有所有内容的图层并摆脱UIView本身? 我已经尝试过这个:

UILabel* label;
[...]
[mainLayer addSublayer:[label.layer copy]];
[label release];

但是每当我释放UIView时,图层的内容也被删除。这是否可能,或者UIView的层总是需要UIView本身来显示其内容?我认为图层就像一种画布,UIView将其绘制在上面。我猜我可能对这个假设不正确 :)
6个回答

4

我不明白为什么您无法复制一个图层。虽然一个图层是UIView的“组成部分”,但它最终只是另一个带有几个属性的对象。

实际上,CALayer有一个方法:

- (id)initWithLayer:(id)layer

但它并不是用来复制图层的。 (您可以阅读苹果公司的文档了解原因)
CALayer 不符合 NSCopying 协议,所以您有两个选择:
1. 子类化它,并实现 "copyWithZone:"(并符合 NSCopying 协议) 2. 编写一个方法/函数,将返回 CALayer 的“副本”
无论您选择哪种方式,您必须问自己的问题是:您要复制 CALlayer 的哪些属性?
假设您只想复制内容和框架:
CALayer copyLayer = [CALayer layer];

copyLayer.contents = theLayerToBeCopied.contents;
copyLayer.frame = theLayerToBeCopied.frame;

return copyLayer;

你可以逐个复制图层的每个属性,或者只复制你需要的属性。将这个方法放在CALayer类别中可能是一个不错的选择。


1
也许是因为图层的目的是渲染其关联的UIView及其子层。如果您释放了UIView并使其消失,那么为什么还需要使用最初与该UIView相关联的图层呢?如果您真的需要一个图层,我认为您也需要它的UIView。Haentz可以尝试您建议的方法(我不确定它是否有效),但我在核心动画代码中没有看到过这种情况。此外,如果苹果公司考虑使这种可能性成为现实,它会使CALayer符合NSCopying。请告诉我这种方法是否有效。 - Massimo Cafaro
我能想到复制CALayer的唯一原因是需要在屏幕上显示多个相同的图层。通常,您会以与创建第一个图层相同的方式创建多个图层。尽管如此,如果您打算销毁第一个图层,我不明白为什么要复制它。我的想法是,他实际上并不需要“复制”,而是需要具有与原始图层相同属性的图层。你是对的,这可能不是问题的被接受解决方案,但很有趣看看它是如何工作的。 - Corey Floyd

1

这是不可能的:一个图层是UIView的属性。因此,当您释放UIView时,它的图层也会消失。您将图层视为一种画布的想法并没有错。但是,图层是其UIView的组成部分。


1

UIViews在iOS中不是很重。大多数情况下,您可以将它们视为CALayer的支持包装器。与在Mac上不必由CALayer支持的NSView不同,在iOS上不是这样的。 所有 UIView实例都是CALayer支持的,这就是大部分工作量的来源。 Apple的文档甚至说过像“不要费心去动画化一个UIView的图层。直接动画化UIView,因为它本质上只是将所有内容发送到图层。“(当然是改写过的)

重点是,除非您特别地需要UILayer实例来处理UIView不直接支持的内容,否则只需完全使用UIView即可。


0

你也可以完全绕过UILabel,使用CATextLayer创建你的文本。


0
使用CAReplicatorLayer,您将能够完全复制该层。

不,那不是该类的作用。它无法解决提问者尝试做的事情。 - clearlight

0

UILabel并不是一个非常复杂的控件。我建议您放弃这种攻击方式,学习使用Quartz绘制您想要的内容到新的CGImage中。然后,您可以将其分配给CALayer的contents属性,而无需担心所有这些其他内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接