我正在尝试使用 CAShapeLayer
来屏蔽我的 iOS
应用程序中的 CALayer
,因为它只占用 CPU 时间的一小部分
在 bitmap context
中屏蔽图像与手动屏蔽图像;
当我有几十个或更多的图像相互分层时,CAShapeLayer
被屏蔽的 UIImageView
移动到我的触摸很慢。
下面是一些示例代码:
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"SomeImage.jpg" ofType:nil]];
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0.f, 0.f, image.size.width * .25, image.size.height * .25));
for (int i = 0; i < 200; i++) {
SLTUIImageView *imageView = [[SLTUIImageView alloc]initWithImage:image];
imageView.frame = CGRectMake(arc4random_uniform(CGRectGetWidth(self.view.bounds)), arc4random_uniform(CGRectGetHeight(self.view.bounds)), image.size.width * .25, image.size.height * .25);
CAShapeLayer *shape = [CAShapeLayer layer];
shape.path = path;
imageView.layer.mask = shape;
[self.view addSubview:imageView];
[imageView release];
}
CGPathRelease(path);
使用上面的代码,imageView
非常卡顿。但是,如果我在 bitmap context
中手动屏蔽它,它会立即使用react:
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"3.0-Pad-Classic0.jpg" ofType:nil]];
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0.f, 0.f, image.size.width * .25, image.size.height * .25));
for (int i = 0; i < 200; i++) {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width * .25, image.size.height * .25), NO, [[UIScreen mainScreen]scale]);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddPath(ctx, path);
CGContextClip(ctx);
[image drawInRect:CGRectMake(-(image.size.width * .25), -(image.size.height * .25), image.size.width, image.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
SLTUIImageView *imageView = [[SLTUIImageView alloc]initWithImage:finalImage];
imageView.frame = CGRectMake(arc4random_uniform(CGRectGetWidth(self.view.bounds)), arc4random_uniform(CGRectGetHeight(self.view.bounds)), finalImage.size.width, finalImage.size.height);
[self.view addSubview:imageView];
[imageView release];
}
CGPathRelease(path);
顺便说一下,这是 SLTUIImageView
的代码,它只是 UIImageView
的一个简单子(monad)类,可以响应触摸(对于任何想知道的人):
-(id)initWithImage:(UIImage *)image{
self = [super initWithImage:image];
if (self) {
self.userInteractionEnabled = YES;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.superview bringSubviewToFront:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
self.center = [touch locationInView:self.superview];
}
是否有可能以某种方式优化 CAShapeLayer
屏蔽 UIImageView
的方式,从而提高性能?我试图在 Instruments
中使用 Time Profiler
找出瓶颈在哪里,但我无法确切地说出是什么原因造成的。
我已经尝试在 layer
和 layer.mask
上将 shouldRasterize
设置为 YES
但似乎都没有有什么影响。我不确定该怎么做。
编辑:
我做了更多测试,发现如果我只使用一个普通的 CALayer
来屏蔽另一个 CALayer (layer.mask = someOtherLayer)
我会遇到同样的性能问题。看起来问题并不特定于 CAShapeLayer
,而是特定于 CALayer
的 mask
属性。
编辑 2:
因此,在详细了解了如何在 Instruments
中使用 Core Animation 工具
之后,我了解到 View 每次移动时都会在屏幕外渲染。在触摸开始时将 shouldRaster
设置为 YES
并在触摸结束时将其关闭,使 instruments
中的 View 保持绿色(从而保持缓存) ,但性能仍然很糟糕。我相信这是因为即使 View 被缓存,如果它不是不透明的,那么它仍然必须在每一帧中重新渲染。
需要强调的一件事 是,如果只有少数几个 View 被屏蔽(甚至大约 10 个),则性能相当不错。但是,当您将其增加到 100 或更多
时,性能会下降。我想这是因为当一个移动到其他上时,它们都必须重新渲染。
我的结论是,我有两个选择之一。
首先,必须有某种方法可以永久屏蔽 View (渲染一次并称其为好)。我知道这可以通过我在示例代码中显示的图形或位图上下文路由来完成,但是当图层遮盖其 View 时,它会立即发生。当我在如图所示的位图上下文中执行此操作时,它非常慢(因为它几乎无法比较它有多慢)。
其次,必须有一些更快
的方法通过位图上下文路由来完成。如果有屏蔽图像或 View 方面的专家,将不胜感激他们的帮助。
最佳答案
您已经走了很远,我相信几乎可以找到解决方案。我要做的只是扩展您已经尝试过的内容。因为你说这些层中的许多层在最终位置“结束”,相对于其他层和蒙版保持不变。所以只需将所有这些“完成”层渲染到单个位图上下文。这样,每次您为该单一上下文写出一层时,您就会少担心一层会减慢动画/渲染过程。
关于ios - 使用多个 CALayer 蒙版时的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17054374/