ios - 使用多个 CALayer 蒙版时的性能问题

标签 ios objective-c performance calayer masking

我正在尝试使用 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 找出瓶颈在哪里,但我无法确切地说出是什么原因造成的。

我已经尝试在 layerlayer.mask 上将 shouldRasterize 设置为 YES 但似乎都没有有什么影响。我不确定该怎么做。

编辑:

我做了更多测试,发现如果我只使用一个普通的 CALayer 来屏蔽另一个 CALayer (layer.mask = someOtherLayer) 我会遇到同样的性能问题。看起来问题并不特定于 CAShapeLayer,而是特定于 CALayermask 属性。

编辑 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/

相关文章:

iphone - 如何将字符串数组发送到 UIActionSheet varargs init 方法中?

ios - 为模拟器构建时出现架构 i386 错误的 undefined symbol

performance - Haskell——产生更少 Spark 的平行映射

objective-c - 从自定义单元格返回 NSIndexPath ? (UITableView)

c - 使用 MinGW C 的 Windows QueryPerformanceCounter

performance - 有什么方法可以改善构建/编译时间?

ios - 增加和减少 iOS8 自定义键盘大小

ios - 如何以编程方式创建进度条?

ios - ObjC 中的日期格式化程序问题

ios - 向 xib 中的 "main view"添加约束