Предварительно визуализированная анимация Core Graphics не анимирует плавно и загружает память
Я отправляю этот вопрос в ответ на один изответы на мой предыдущий вопрос здесь:Несколько масок CALayer, вызывающих проблемы с производительностью
Итак, теперь, когда я пытаюсь перейти к подходу с предварительно обработанной анимацией, я все еще не могу получить плавную анимацию. Кроме того, приложение, запускаемое на реальном устройстве, периодически вылетает из-за проблем с памятью.
Вы можете увидеть анимацию, запущенную здесь:http://cl.ly/e3Qu (Это может выглядеть не так плохо с видео, но фокусироваться на краю анимации, и это работает хуже на реальном устройстве.)
Вот мой код:
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()
Функция просто делает довольно простой рисунок Core Graphics, чтобы получить фоновое изображение.
Я могу только предположить, что я делаю что-то в корне неправильно здесь, но я не могу думать о том, что это такое.
Любые предложения о том, как повысить производительность и уменьшить потребление памяти (без ухудшения качества анимации)?