Reputation: 169
I have created an app and it is (well it was) ready to submit.
The app is basically a flash cards apps for kids where there are 12 cards per page.
It is currently iPad only and when the cards are touched a image view animates out of the card to full screen with a full resolution 2048 x 1536 and it plays a sound of the animal, you tap the full size image and it goes back in the card. Each card has 5 images assigned to it. The app has been working perfectly all though the design period and now that I have loaded all of the animals and I have been testing it and noticed it crashed.
Long story short the memory continually grows by 12MB per image (although each image is around 200-400KB) until it reaches 700MB of Memory and it crashes. This memory never reduces.
I have run the app through the xcode instruments and can see no leaks but have identified in the 'Allocations' that it is the 'ImageIO-jpeg-data' category that is the culprit.
I have spent all evening reading up about this as I have found some promising results however these results have not worked for me so I am assuming that I have misunderstood what has been advised or I have not understood so was hoping that someone could maybe help me out or explain in laymen terms how I can resolve this.
OK so to explain how I have the view contoller set up.
Originally I set up the 5 images for each card in an array but there was a delay so someone on here recommended that I pre load the images in viewDidLoad and then call them when the card/button was touched.
So for example I was using this format in viewDidLoad
domestic100 = [UIImage imageNamed:@"ferret-00"];
domestic101 = [UIImage imageNamed:@"ferret-01"];
domestic102 = [UIImage imageNamed:@"ferret-02"];
domestic103 = [UIImage imageNamed:@"ferret-03"];
domestic104 = [UIImage imageNamed:@"ferret-04"];
and then in the the button pressed I assigned the image to the image view by calling:
domestic01ImageContainer.image = domestic100;
inside a if else look checking if the image number was 1 to 4.
Anyway it worked perfectly (apart form this memeory issue)
I have read online that I would be better off declaring the uiimages using
[UIImage imageWithContentsOfFile:path]
as seen in this post: UIImage memory not deallocating VM: ImageIO_JPEG_DATA?
So the alterations I have made in my code are:
in my viewDidLoad I now create uiimages as so:
domestic200 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"dog-00" ofType: @"jpg"]];
domestic201 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"dog-01" ofType: @"jpg"]];
domestic202 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"dog-02" ofType: @"jpg"]];
domestic203 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"dog-03" ofType: @"jpg"]];
domestic204 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"dog-04" ofType: @"jpg"]];
and then in the button pressed call the image in to the imageview using
[domestic01ImageContainer setImage:domestic100];
I am getting the same results - the image are just building up in the same memory and not releasing or deallocating.
I'm no wiz when it comes of objective-c and this is my first real app.
If someone could be kind enough to spare a moment of their time to help me I would be really appreciative.
Thanks in advance.
****** Edit ******
So I have told you how I load my images above, I also in the viewDidLoad give the 12 imageviews a starting point and a hidden alpha.
domestic01ImageContainer = [[UIImageView alloc] initWithFrame:CGRectMake(30, 123, 152, 224)];
domestic01ImageContainer.Alpha = 0;
I then add the subview with:
[self.view addSubview:domestic01ImageContainer];
each imageview is allocated a tap gesture to hide the image at a later point:
UITapGestureRecognizer *domestic01Tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageTaped:)];
[domestic01ImageContainer addGestureRecognizer:domestic01Tap];
[domestic01ImageContainer setUserInteractionEnabled:YES];
When the thumb / card is pressed a streamlined version of the button would be:
- (IBAction)domestic01ButtonClicked:(id)sender {
static int imageNumber = 0;
if (imageNumber == 0) {
[domestic01ImageContainer setImage:domestic100];
imageNumber++;
}
else if (imageNumber == 1) {
[domestic01ImageContainer setImage:domestic101];
imageNumber++;
}
else if (imageNumber == 2) {
[domestic01ImageContainer setImage:domestic102];
imageNumber++;
}
else if (imageNumber == 3) {
[domestic01ImageContainer setImage:domestic103];
imageNumber++;
}
else if (imageNumber == 4) {
[domestic01ImageContainer setImage:domestic104];
imageNumber = 0;
}
domestic01ImageContainer.Alpha = 1;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
domestic01ImageContainer.frame = CGRectMake(0, 0, 768, 1024);
} completion:^(BOOL finished) {
}];
}
The in my imageTapped recognizer to shrink the full size image back to the card I use:
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
domestic01ImageContainer.frame = CGRectMake(30, 123, 152, 224);
} completion:^(BOOL finished) {
domestic01ImageContainer.Alpha = 0;
}];
Which basically put the flash card back from full screen to the size of the card / thumbnail and the sets alpha again to 0.
Like I said it all works but as you have suggested the image is being retained somewhere.
Hope this sheds a bit more light on what could be causing the issue.
I had tried setting the image to nil in after the alpha was set to 0 in the imageTapped but this didn't clear the memory.
[domestic05ImageContainer setImage:nil];
Upvotes: 5
Views: 3958
Reputation: 612
I was having a similar issue. Memory was being held on abnormally. I had a UIImageView IBOutlet and I was setting its image property with my view controller's UIImage property, which I would set while initializing my view controller. The UIImageView would hold on to the UIImage property of my view controller wrongly even when I would go back to the root view controller.
I fixed the issue by changing the view controller's UIImage property to NSData and setting the UIImageView's image property as follows:
[_previewImageView setImage:[UIImage imageWithData:_previewImageData]];
This resolved the issue of ImageIO-jpeg-data being help on unnecessarily. Hope this helps someone.
Upvotes: 1
Reputation: 169
Ok so if anyone else is suffering from this issue then here is the solution that I found that work perfectly.
http://xcodenoobies.blogspot.co.uk/2011/02/best-way-to-use-uiimageview-memory.html
Thanks Anna for your input, it pointed me in the right direct but his was the answer that did it for me.
Upvotes: 6