预渲染的核心graphicsanimation不会顺利地animation和内存

我发布这个问题是为了回应我之前问题中的一个答案 : 多个CALayer掩码导致性能问题

所以,现在我试图按照预先渲染的animation方法,我仍然无法获得stream畅的animation。 不仅如此,在实际设备上运行时,由于内存问题,应用程序会定期崩溃。

你可以看到在这里运行的animation: http : //cl.ly/e3Qu (video看起来不那么糟糕,但是关注animation的边缘,在实际的设备上performance更差)。

这是我的代码:

static CGFloat const animationDuration = 1.5; static CGFloat const calculationRate = (1.0/40.0); // 40fps max. static CGFloat const calculationCycles = animationDuration/calculationRate; @implementation splashView { CADisplayLink* l; CGImageRef backgroundImg; UIColor* color; NSMutableArray* animationImages; NSTimeInterval currentTime; } -(void) beginAnimating { static dispatch_once_t d; dispatch_once(&d, ^{ CGFloat totalDistance = 0; CGFloat screenProgress = 0; CGFloat deltaScreenProgress = 0; totalDistance = screenHeight()+screenWidth(); color = [[lzyColors colors] randomColor]; backgroundImg = textBG(color, screenSize()).CGImage; animationImages = [NSMutableArray array]; NSLog(@"start"); UIGraphicsBeginImageContextWithOptions(screenSize(), YES, 0); CGContextRef c = UIGraphicsGetCurrentContext(); for (int i = 0; i <= (calculationCycles+1); i++) { UIImage* img = lzyCGImageFromDrawing(^{ CGFloat height = screenHeight(); CGFloat width = screenWidth(); CGMutablePathRef p = CGPathCreateMutable(); CGPoint startingPoint = [self pointBForProgress:screenProgress]; CGPathMoveToPoint(p, nil, startingPoint.x, startingPoint.y); lzyCGPathAddLineToPath(p, [self pointAForProgress:screenProgress]); if ((width < screenProgress) && (screenProgress-deltaScreenProgress) < width) { lzyCGPathAddLineToPath(p, (CGPoint){width, 0}); } if (deltaScreenProgress != 0) lzyCGPathAddLineToPath(p, [self pointAForProgress:screenProgress-deltaScreenProgress-1]); if (deltaScreenProgress != 0) lzyCGPathAddLineToPath(p, [self pointBForProgress:screenProgress-deltaScreenProgress-1]); if ((height < screenProgress) && (screenProgress-deltaScreenProgress) < height) { lzyCGPathAddLineToPath(p, (CGPoint){0, height}); } CGPathCloseSubpath(p); CGContextAddPath(c, p); CGContextClip(c); CGPathRelease(p); CGContextSetFillColorWithColor(c, color.CGColor); CGContextFillRect(c, self.bounds); CGContextDrawImage(c, self.bounds, backgroundImg); }); [animationImages addObject:img]; deltaScreenProgress = screenProgress; screenProgress = (i*totalDistance)/calculationCycles; deltaScreenProgress = screenProgress-deltaScreenProgress; } NSLog(@"stop"); currentTime = 0; l = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire)]; [l addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; }); } -(void) displayLinkDidFire { NSTimeInterval deltaTime = l.duration; currentTime += deltaTime; if (currentTime <= animationDuration) { CGFloat prg = (currentTime/animationDuration); NSInteger image = roundf(([animationImages count]-1)*prg); [CATransaction begin]; [CATransaction setDisableActions:YES]; self.layer.contents = (__bridge id _Nullable)(((UIImage*)[animationImages objectAtIndex:image]).CGImage); [CATransaction commit]; } else { [CATransaction begin]; [CATransaction setDisableActions:YES]; self.layer.contents = (__bridge id _Nullable)(((UIImage*)[animationImages lastObject]).CGImage); [CATransaction commit]; [l invalidate]; animationImages = nil; } } -(CGPoint) pointAForProgress:(CGFloat)progressVar { CGFloat width = screenWidth(); return (CGPoint){(progressVar<width)?progressVar:width+1, (progressVar>width)?progressVar-width:-1}; } -(CGPoint) pointBForProgress:(CGFloat)progressVar { CGFloat height = screenHeight(); return (CGPoint){(progressVar>height)?(progressVar-height):-1, (progressVar<height)?progressVar:height+1}; } @end 

textBG()函数只是做一些相当简单的核心graphics绘制来获取背景图像。

我只能假设我在这里做了一些根本性的错误,但我想不出来是什么。

有关如何提高性能和降低内存消耗(不降低animation质量)的build议?

通过图层内容animation全屏图像肯定会出现性能和内存问题,特别是在@ 3x设备上。 对于您在其他问题( 本video )中显示的animation,看起来并不像实际上需要任何遮罩 – 创build一系列长方形纯色层(黑色,浅紫色,中等紫色,深紫色),将它们从前到后(文字层位于中间和中间之间)进行分层,将它们旋转到所需的angular度,然后根据需要移动它们。

如果你最终需要一个更复杂的animation,那么这种方法不适用于或者一般来说,为任意的全屏内容制作animation,你需要(1)将它预渲染为video(离线或使用AVFoundation APIs)并以此方式播放,或(2)使用OpenGL或Metal进行绘制。

你在那里遇到的问题是一些写得不好的animation逻辑,它基本上是在内存中分配一大堆图片,这种方式肯定会在以后的一段时间内让你的设备崩溃。 您需要从一个更好的方法开始,不要将所有图像数据同时存入内存。 不要试图调整你已经拥有的东西,因为以前的开发者做出的基本假设是错误的。 看到我以前的例子像一个像“video和内存使用的IOS设备”一个很好的链接类似的问题: https : //stackoverflow.com/a/17224710/763355