使用许多CALayer掩码时的性能问题

dav*_*Mac 23 performance objective-c masking calayer ios

我试图用来CAShapeLayer掩盖CALayer我的iOS应用程序,因为它需要一小部分CPU time掩盖图像与手动屏蔽一个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);
Run Code Online (Sandbox Code Playgroud)

有了上面的代码,imageView是非常滞后的.但是,如果我手动屏蔽它,它会立即作出反应bitmap context:

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);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这里是代码SLTUIImageView,它只是一个UIImageView响应触摸的简单子类(对于任何想知道的人):

-(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];
}
Run Code Online (Sandbox Code Playgroud)

是否有可能以某种方式优化CAShapeLayer屏蔽效果,UIImageView从而提高性能?我试图找出瓶颈是使用Time ProfilerInstruments,但我不能告诉到底是什么原因造成的.

我已尝试设置shouldRasterizeYESon layer和on,layer.mask但似乎都没有任何效果.我不知道该怎么做.

编辑:

我做了更多的测试,并发现如果我只使用常规CALayer来掩盖另一个CALayer (layer.mask = someOtherLayer)我有相同的性能问题.似乎问题并不是特定于 - CAShapeLayer它是特定于mask财产的CALayer.

编辑2:

因此,在了解了有关使用Core Animation toolin的更多信息之后Instruments,我了解到视图每次移动时都会在屏幕外呈现.设置shouldRasterYES触摸开始时和触摸结束时将其关闭使视图保持绿色(从而保持缓存)instruments,但性能仍然很糟糕.我相信这是因为即使视图被缓存,如果它不是不透明的,那么它仍然必须用每个帧重新渲染.

需要强调的一点是,如果只有少数几个视图被屏蔽(甚至大约十个),那么性能非常好.但是,当你增加它时100 or more,性能会滞后.我想这是因为当一个人移过其他人时,他们都必须重新渲染.

我的结论是,我有两种选择之一.

首先,必须有一些永久屏蔽视图(渲染一次并称之为好).我知道这可以通过我在示例代码中显示的图形或位图上下文路由来完成,但是当图层屏蔽其视图时,它会立即发生.当我在如图所示的位图上下文中执行时,它非常慢(因为它几乎甚至无法比较它的速度有多慢).

其次,必须有一些faster方法通过位图上下文路由来完成它.如果有专家屏蔽图像或视图,他们的帮助将非常感谢.

Ale*_*ray 1

您已经取得了很大的进展,我相信已经快找到解决方案了。我要做的只是你已经尝试过的事情的延伸。既然您说这些图层中的许多“最终”位置相对于其他图层和蒙版保持不变,那么只需将所有这些“完成”图层渲染到单个位图上下文即可。这样,每次您向该单一上下文写入一个图层时,您就可以少一个图层来担心会减慢动画/渲染过程。