guardabrazo
guardabrazo

Reputation: 1229

Delay loading images in UIImageView

I'm trying to loop through some images in a single UIImageView when I tap a button. The image must disappear 0.1 seconds after the button is pressed. Here's the code:

int tapCount = 0;

UIImage *image0 = [UIImage imageNamed:@"0.jpg"];
UIImage *image1 = [UIImage imageNamed:@"1.jpg"];
UIImage *image2 = [UIImage imageNamed:@"2.jpg"];
imagesArray = [[NSArray alloc] initWithObjects:image0, image1, image2, nil];


-(IBAction)backgroundButton:(id)sender{

  self.myImageView.image = [imagesArray objectAtIndex:tapCount%3];
  tapCount++;
  [self performSelector:@selector(eraseImage) withObject:self afterDelay:0.1];   
}

-(void)eraseImage{

  self.myImageView.image = nil;
}

The problem is that the images don't appear until I've completed one entire loop (at the 4th tap). I'm guessing that somehow I must initialize the images in the UIImageView because it takes some time between the tapping and the image appearing, and since it disappears after 0.1 seconds...it doesn't show at all.

I've tried loading them inside viewDidLoad like this:

for(int i = 0; i<[imagesArray count]; i++){
  self.myImageView.image = [imagesArray objectAtIndex : i];
}

But it only works with the last image that loads (image2 in this case).

Should I loop between different UIImageView instead of looping through different UIImage inside a single UIImageView?

Any other hints?

Upvotes: 0

Views: 1080

Answers (4)

guardabrazo
guardabrazo

Reputation: 1229

I finally managed to work this around using this solution:

First I preload all the images in the background thread

-(void)preload:(UIImage *)image{

CGImageRef ref = image.CGImage;
size_t width = CGImageGetWidth(ref);
size_t height = CGImageGetHeight(ref);
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, space, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
CGContextRelease(context);
}

Then I execute the same action I had in the beginning:

-(IBAction)backgroundButton:(id)sender{

   self.myImageView.image = [imagesArray objectAtIndex:tapCount%3];
   tapCount++;
   [self performSelector:@selector(eraseImage) withObject:self afterDelay:0.1];   
}

-(void)eraseImage{

  self.myImageView.image = nil;
}

Upvotes: 0

Mika
Mika

Reputation: 5845

I think there is a much simpler way to achieve that animation you are going for. Try the following code:

-(IBAction)backgroundButton:(id)sender{


  [UIView animateWithDuration:0.2
                        delay:nil 
                      options:UIViewAnimationCurveEaseIn 
                   animations:^{
                        self.myImageView.image = [imagesArray objectAtIndex:tapCount%3];
                        self.myImageView.image = nil;

                       } 
             completion:nil
   ];

  tapCount++;

  if (tapCount == 2) {
       tapCount = 0;
  }

 }

Upvotes: 0

Wain
Wain

Reputation: 119031

Creating a UIImage doesn't actually load the image data (you need to render it to a context for that to happen). So, if your images are large then you could be hiding them before they are actually rendered to the screen. You won't be able to hold many images in memory at the same time, but you can force the image data to be loaded by creating a context and drawing the image into it (which can be done in the background, using CGContextDrawImage).

There are a few 3rd party bits of code which do this, like this or check this discussion.

Upvotes: 2

Related Questions