I have an app that creates an animation from images stored in a group in my project navigator (not Images.xcassets). This code "works" in that it animates properly, but using imageNamed causes a memory leak because the image files are not getting deallocated.
I can't figure out why adding with imageNamed: works adds images to my array, but imageWithContentsOfFile: doesn't.
A little info on the mechanics of my app:
self.myPhoto is set on the segue from another ViewController. The number of images can vary, so I test to see the file is "there" before adding it to the array.
Filenames follow this naming convention:
"1-1.jpg"
"2-1.jpg"
"2-2.jpg"
"99-1.jpg"
"99-2.jpg"
"99-3.jpg"
"99-4.jpg"
This code works, but the images don't deallocate, causing a memory leak:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:@"%@-%d.jpg", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
[imageArray addObject:[UIImage imageNamed:fileName]];
} else {
// otherwise, don't add image to the array
break;
}
}
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
I ran Instruments on it and saw I had a memory leak emanating from my animation. Digging around a little on StackOverflow, I discovered the manner I'm adding my files to myArray results in images not getting deallocated.
So I tried this, instead:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:@"%@-%d", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
[imageArray addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"%@", fileName] ofType:@"jpg"]]];
NSLog(@"%@ added to imageArray", fileName);
} else {
// otherwise, don't add image to the array
break;
}
}
NSLog(@"There are %lu images in imageArray", (unsigned long)imageArray.count);
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
When I do it this way, the page where the animation loads appears, but the images don't get added to my array--the . This is a well-documented issue. Here are a few posts covering this problem:
Dirty Memory because of CoreAnimation and CG image
How do I use imageWithContentsOfFile for an array of images used in an animation?
Thank you for reading. I'm stumped, though I'm confident the resolution to this problem is a startlingly stupid oversight on my part. Prove me right ;)
I made some minor changes out of desperation and I stumbled into the "answer". Comments note where I made changes:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
// I set the filename here, adding .jpg to it
NSString *fileName = [NSString stringWithFormat:@"%@-%d.jpg", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
// I blanked out ofType, as it's set when I create the local fileName variable
[imageArray addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"%@", fileName] ofType:@""]]];
} else {
// otherwise, don't add image to the array
break;
}
}
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With