iPhone app memory leak with UIImage animation? Problem testing on device - iphone

I have an animation which works fine in the simulator but crashes on the device. I am getting the following error...
Program received signal: “0”.
The Debugger has exited due to signal 10 (SIGBUS)
A bit of investigating suggests that the UIImages are not getting released and I have a memory leak. I am new to this so can someone tell me if this is the likely cause? If you could also tell me how to solve it then that would be amazing.
The images are 480px x 480px and about 25kb each. My code is below...
NSArray *rainImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"rain-loop0001.png"],
[UIImage imageNamed:#"rain-loop0002.png"],
[UIImage imageNamed:#"rain-loop0003.png"],
[UIImage imageNamed:#"rain-loop0004.png"],
[UIImage imageNamed:#"rain-loop0005.png"],
[UIImage imageNamed:#"rain-loop0006.png"],
//more looping images
[UIImage imageNamed:#"rain-loop0045.png"],
[UIImage imageNamed:#"rain-loop0046.png"],
[UIImage imageNamed:#"rain-loop0047.png"],
[UIImage imageNamed:#"rain-loop0048.png"],
[UIImage imageNamed:#"rain-loop0049.png"],
[UIImage imageNamed:#"rain-loop0050.png"],
nil];
rainImage.animationImages = rainImages;
rainImage.animationDuration = 4.15/2;
rainImage.animationRepeatCount = 0;
[rainImage startAnimating];
[rainImage release];
Thanks

I'm pretty sure you're crashing because [NSArray arrayWithObjects:] returns an auto-released object which you're storing to rainImage. Then at the bottom you're releasing rainImage again, thus over releasing it.

The root of the problem is that you are running out of main memory because you have too many decompressed images in memory, see my answer to uiimage-animation-causing-app-to-crash-memory-leaks for the reason you should not be using UIImageView.animationImages.

Related

iPhone showing Different to the Simulator

.
Hello,
First of all, this question may seem similar to my last, but it isn't. For reference if you must compare it is here Previous Question
Now I have developed an app and it runs perfectly on the iPhone Simulator. It does not use anything the Simulator cannot handle.
I have a button, generated in code and it appears on my mac in the simulator, but not on the 2 tested devices. 1) iPhone4 and the 2) iPod Touch 4th Gen.
How is that possible?
-(void)popUpMenu
{
UIImage *image = [UIImage imageNamed:#"Menu01#2x.png"];
UIImage *selectedImage = [UIImage imageNamed:#"Menu02#2x.png"];
UIImage *toggledImage = [UIImage imageNamed:#"Done01#2x.png"];
UIImage *toggledSelectedImage = [UIImage imageNamed:#"Done02#2x.png"];
NSArray *buttons = [NSArray arrayWithObjects:b1, b2, b3, b4, b5, nil];
RNExpandingButtonBar *bar = [[RNExpandingButtonBar alloc] initWithImage:image selectedImage:selectedImage toggledImage:toggledImage toggledSelectedImage:toggledSelectedImage buttons:buttons center:center];
// RNExpandingButtonBar *bar = [[UIButton buttonWithType:UIButtonTypeRoundedRect] initWithArray:buttons];
[bar setHorizontal:NO];
[bar setExplode:NO];
[self.view addSubview:bar];
[self setBar:bar];
}
The array is a set of buttons that appear from this. The link to the Github is:
Github - RNExpandingButtonBar
Then I use this code in viewDidLoad method to display the button
[self popUpMenu];
Cheers Jeff
Check the case of the image names in your code and in your workspace, the device is case sensitive and OSX by default is not. Thats why it is working in your simulator and not on your device.

Frame with 50 png in iPhone

I have a ViewController with 16 buttons. Each button loads a popover that show 50 frames renders in moving.
What is the best form to do it?
I know that imageWithName is bad because it load all images in cache, and for this reason im doing it with:
myAnimatedView.animationImages=[NSArray arrayWithObjects:
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0000",nombrePieza]ofType:#"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0001",nombrePieza]ofType:#"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0002",nombrePieza]ofType:#"png"]],
...
...
... [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0050",nombrePieza]ofType:#"png"]],nil];
But when i load about 10 times the popover with differents frames, i have a leak of memory only on my device, but not in the simulator.
For this reason, i want know which is the best form to do it?
With a video? or with CAAnimation?
Thanks for help.
You better use a timer in this case, not to have memory problems
...
page = 1;
imageAnim = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[[self view] addSubview:imageAnim];
tim = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(avv) userInfo:nil repeats:YES];
...
- (void)avv {
UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"SplashAnimation %03d", page] ofType:#"png"]];
[imageAnim setContentMode:UIViewContentModeScaleToFill];
[imageAnim setImage:img];
page++;
if(page > maxNumberFrame) {
[tim invalidate];
}
}
This is an example to get ideas
imageNamed does not cause a leak in itself (although some previous discussions suggest it may have had bugs in pre iOS 4).
However, imageNamed will cache your images so that you don't load them for every instance if the image that you show. In your case, if you load the animation 10 times, I think you will see that each image gets loaded only once. Your current solution will force your images to be loaded every time.
Most importantly, the imageNamedmethod will transparantly handle the Retina version of the images, which you would have to do manually otherwise.
From the documentation:
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.

Image Saving to Albums working fine in Simulator but gives EXC_BAD_EXCESS on device

I want to save an image into albums.
I am doing it using UIImageWriteToSavedPhotosAlbum API.
Its working perfectly fine on Simulator, but crashes on Device giving EXC_BAD_EXCESS.
I have enables NSZombi.. argument, but it shows no log of any deallocated memory reused.
- (IBAction)saveImageOnHDButtonPressed:(id)sender{
NSArray *subviews = [scroll subviews];
UIImage *img = [[subviews objectAtIndex:0] image];
UIImageWriteToSavedPhotosAlbum(img, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
Please help..
Thanks
Try retaining the image before you save it.

iPhone App crashes after switching, possibly due to UIImage imageNamed

My app moves 10 UIImageViews randomly around the screen, and once an UIImageView hits the corner, it changes its image. The problem is: after switching between apps and going back to mine, the app crashes.
The console gives me this message:
"App" exited abnormally with signal 10: Bus error
The crash log states this:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000011
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
I think the problem is due to the fact that I'm using UIImage imageNamed, here is the code:
In ViewController.h:
UIImage *red;
UIImage *green;
UIImage *blue;
UIImageView *ballOne;
UIImageView *ballTwo;
UIImageView *ballThree;
UIImageView *ballFour;
// And declare UIImageView for other balls
int clr
In ViewController.m:
- (void)viewDidLoad {
...
red = [UIImage imageNamed: #"redTexture.png"];
green = [UIImage imageNamed: #"greenTexture.png"];
blue = [UIImage imageNamed: #"blueTexture.png"];
...
}
- (void)moveAll:(NSTimer *)theTimer{
...
// If UIImageView touches a corner, Do this:
clr = arc4random()%3 + 1;
switch (clr) {
case 1:
[ballOne setImage:red];
break;
case 2:
[ballOne setImage:green];
break;
case 3:
[ballOne setImage:blue];
break;
default:
break;
}
// And do this for the rest of 9 "balls"
}
Why does my App crash, and how do I solve it?
[UIImage imageNamed:] returns an autoreleased instance of a UIImage. That means that the memory will be released as soon as the event loop ends.
Yo need to retain those instance either by calling.
[[UIImage imageNamed:#"blabl.png"] retain]
or (preferred method) by setting up your blue, red, green members as property with
#property(nonatomic, retain) UIImage* red;
and your code will be like :
- (void)viewDidLoad {
...
self.red = [UIImage imageNamed: #"redTexture.png"];
self.green = [UIImage imageNamed: #"greenTexture.png"];
self.blue = [UIImage imageNamed: #"blueTexture.png"];
...
}
Of course do not forget to release them when your done otherwize you will have the opposite of what you have now : memory leaks.
to release red, call
[red release]
inthe dealloc method.
A bus error means that you're attempting to access memory that the CPU physically cannot access. You probably have a stray pointer.
Maybe try the memory allocation debugger?

Free memory after iphone animation

My app crashes due to memory building up after every animation.
Here is my sample code:
-(IBAction) shoot: (id)delegate{
[gun setImage:[UIImage imageNamed:#"animation_machin_guns_320x480_7.png"]];
UIImage *frame1 = [UIImage imageNamed:#"animation_machin_guns_320x480_1.png"];
UIImage *frame2 = [UIImage imageNamed:#"animation_machin_guns_320x480_2.png"];
UIImage *frame3 = [UIImage imageNamed:#"animation_machin_guns_320x480_3.png"];
UIImage *frame4 = [UIImage imageNamed:#"animation_machin_guns_320x480_4.png"];
UIImage *frame5 = [UIImage imageNamed:#"animation_machin_guns_320x480_5.png"];
UIImage *frame6 = [UIImage imageNamed:#"animation_machin_guns_320x480_6.png"];
UIImage *frame7 = [UIImage imageNamed:#"animation_machin_guns_320x480_7.png"];
gun.animationImages = [[NSArray alloc] initWithObjects:frame1, frame2, frame3, frame4, frame5, frame6, frame7,nil];
gun.animationDuration = 1;
gun.animationRepeatCount = 1;
[gun startAnimating];
[frame1 release];
[frame2 release];
[frame3 release];
[frame4 release];
[frame5 release];
[frame6 release];
[frame7 release];}
Releasing the frames doesn't seem to do the magic.
I tried using this http://kosmaczewski.net/projects/iphone-image-cache/ for image caching but i guess I don't know how to use it properly since the memory builds up faster than using imageNamed.
Replace [[NSArray alloc] initWithObjects:xxx]; with [NSArray arrayWithObjects:xxx];.
Currently, the array object is being retained twice (once effectively by alloc and once by gun.animationImages = xxx), but only released once (when the gun object is released, or the animationImages property is set to something new), meaning it will never be released.
The arrayWithObjects method returns an autoreleased object, meaning it doesn't need to be manually released by you.
If I were you I would think about only animating parts of the screen or perhaps compressing the images into low quality jpgs or something along those lines.