Daniel Gillespie
Daniel Gillespie

Reputation: 535

UIImageView animation delay when doing startAnimating

I have an animation of a menu background that is 21 frames. I load them into memory using the below code in the view's viewDidLoad method.

NSMutableArray *menuanimationImages = [[NSMutableArray alloc] init];

for( int aniCount = 0; aniCount < 21; aniCount++ )
{

    NSString *fileLocation = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: @"bg%i", aniCount + 1] ofType: @"png"];
    NSData *imageData = [NSData dataWithContentsOfFile: fileLocation];

    [menuanimationImages addObject: [UIImage imageWithData:imageData]];

}

settingsBackground.animationImages = menuanimationImages;

Unfortunately, doing [settingsBackground startAnimating]; doesn't work in the viewDidLoad method. Is there some way to preload the animation so there isn't a 1-3 second delay on first run?

Upvotes: 2

Views: 3344

Answers (4)

MoDJ
MoDJ

Reputation: 4425

The problem with each of these answers is that the suggested "fix" is to preload all your image data into memory. That can and will result in crashes if your images are too big or there are too many images, see my answer for uiimage-animation-causing-app-to-crash-memory-leaks for more detailed info. The real fix is that you need to decompress the images but not hold them all in memory. Or, you can use a movie format that already does the decompression for all frames in one step, so that changing from frame to frame is not a costly operation.

Upvotes: 2

sdsykes
sdsykes

Reputation: 1256

I wouldn't normally recommend using imageNamed and relying on the in-built caching mechanisms. You'll find a lot of discussion on this if you search, but also it won't necessarily pre-render your images anyway.

I use the following code to pre-load and pre-render images so there is no delay when animating the first time through.

NSMutableArray *menuanimationImages = [[NSMutableArray alloc] init];

for (int aniCount = 1; aniCount < 21; aniCount++) {
    NSString *fileLocation = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: @"bg%i", aniCount + 1] ofType: @"png"];
    // here is the code to pre-render the image
    UIImage *frameImage = [UIImage imageWithContentsOfFile: fileLocation];
    UIGraphicsBeginImageContext(frameImage.size);
    CGRect rect = CGRectMake(0, 0, frameImage.size.width, frameImage.size.height);
    [frameImage drawInRect:rect];
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [menuanimationImages addObject:renderedImage];
}

settingsBackground.animationImages = menuanimationImages;

Upvotes: 10

anasaitali
anasaitali

Reputation: 1514

Try the following code, normally you should have no delays. Also this code is simpler :

 NSMutableArray *menuanimationImages = [[NSMutableArray alloc] initWithCapacity:21];
 NSString *imageName;

 for( int aniCount = 1; aniCount < 21; aniCount++ )
 {
     imageName = [NSString stringWithFormat:@"bg%d.png", aniCount];
     [menuanimationImages addObject:[UIImage imageNamed:imageName]];
 }

 settingsBackground.animationImages = menuanimationImages;
 // all frames will execute in 2 seconds
 settingsBackground.animationDuration = 2.0;
 // repeat the annimation forever
 settingsBackground.animationRepeatCount = 0;
 // start animating
 [settingsBackground startAnimating];

Upvotes: -1

Dani Pralea
Dani Pralea

Reputation: 4561

The animationImages property of UIImageView requires an array of UIImage objects, not an array of NSData objects.

You may also want to set the duration and repeatCount, even though they have default values.

Example:

if (!self.idleView.animationImages) {
    self.idleView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"idle1.png"],
                      [UIImage imageNamed:@"idle2.png"],
                      [UIImage imageNamed:@"idle3.png"],
                      [UIImage imageNamed:@"idle4.png"],
                      [UIImage imageNamed:@"idle5.png"],
                      [UIImage imageNamed:@"idle6.png"],
                      [UIImage imageNamed:@"idle7.png"],
                      [UIImage imageNamed:@"idle8.png"],
                      [UIImage imageNamed:@"idle9.png"],
                      [UIImage imageNamed:@"idle10.png"],
                      [UIImage imageNamed:@"idle11.png"],
                      [UIImage imageNamed:@"idle12.png"],
                      [UIImage imageNamed:@"idle13.png"],
                      [UIImage imageNamed:@"idle14.png"],
                      [UIImage imageNamed:@"idle15.png"],
                      [UIImage imageNamed:@"idle16.png"],
                      [UIImage imageNamed:@"idle17.png"],
                      [UIImage imageNamed:@"idle18.png"],
                      [UIImage imageNamed:@"idle19.png"],
                      [UIImage imageNamed:@"idle20.png"]                
                      , nil];
    }
    self.idleView.animationRepeatCount = 0;
    self.idleView.animationDuration = 2.0;
    [self.view addSubview:self.idleView];
    [self.view sendSubviewToBack:self.idleView];
    [self.idleView startAnimating];

Upvotes: 0

Related Questions