iOS CAKeyframeAnimation проблема с памятью - PullRequest
0 голосов
/ 04 января 2019

У меня есть 100 изображений PNG, и я использую CAKeyframeAnimation для создания слоя, который будет воспроизводить анимацию.

Код выглядит так:

CAKeyframeAnimation *kfa = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
kfa.values = animationImages; //CGImage type
kfa.removedOnCompletion = NO;
kfa.duration = 3.f;
kfa.repeatCount = CGFLOAT_MAX;
[layer addAnimation:kfa forKey:nil];

Каждое изображение1338 * 1338 пикселей, поэтому при рендеринге этой анимации память поднимается до небес.(1338 *1338* 4B)

Так как же уменьшить использование памяти и получить приемлемую производительность?

1 Ответ

0 голосов
/ 04 января 2019

Я бы избегал анимации ключевых кадров при этом.Простой таймер должен быть в состоянии выполнить вашу работу, но вы также можете посмотреть на нативную функциональность UIImageView.Есть свойство animationImages.Пожалуйста, посмотрите на этот пост .Хотя этот также потребляет абсурдное количество памяти.

В любом случае, если вы решите сделать это вручную, все равно убедитесь, что вы освободили свою память как можно скорее.Вам по-прежнему могут понадобиться некоторые внутренние пулы авто-релиза:

@autoreleasepool {
    // Code that creates autoreleased objects.
}

Я бы попробовал что-то вроде следующего (не нужно даже никакого дополнительного пула авто-релиза)

+ (void)animateImagesWithPaths:(NSArray *)imagePaths onImageView:(UIImageView *)imageView duration:(NSTimeInterval)duration {
    int count = (int)imagePaths.count;
    if(count <= 0) {
        // No images, no nothing
        return;
    }

    // We need to add the first image instantly
    imageView.image = [[UIImage alloc] initWithContentsOfFile:imagePaths[0]];

    if(count == 1) {
        // Nothing not animate with only 1 image. We are all done
        return;
    }

    NSTimeInterval interval = duration/(NSTimeInterval)(count-1);
    __block int imageIndex = 1; // We need to start with one as first is already consumed

    [NSTimer timerWithTimeInterval:interval repeats:true block:^(NSTimer * _Nonnull timer) {
        if(imageIndex < count) {
            imageView.image = [[UIImage alloc] initWithContentsOfFile:imagePaths[imageIndex]];
            imageIndex++;
        }
        else {
            // Animation ended. Invalidate timer.
            [timer invalidate];
        }
    }];

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...