iPad App Crashes After Loading 30+ Images - ios

Is there a reason the ipad crashes and restarts after loading 30+ images quickly in an image view using this code:
else if([webData isEqualToString:#"ppt33"]){
if(movieisplaying == #"yes"){
UIImage *image = [UIImage imageNamed: #"33.png"];
[imageView setImage:image];
[moviePlayerController stop];
[moviePlayerController.view removeFromSuperview];
movieisplaying = #"no";
}
else{
UIImage *image = [UIImage imageNamed: #"33.png"];
[imageView setImage:image];
}
}
EDIT:
Crash Error - 2012-07-26 13:48:55.172 Stream[5554:707] Received memory warning.

Are all the images and videos in use/visible constantly? From the warning it sounds like you may be exceeding your allotted memory for you app.
This question seems to be related, Received memory warning though it does not detail how to destroy images not in use. I would say try to be smart about when you are loading what image, and then release an image if you are no longer using it. Same goes for the videos. Hope that helps!
EDIT: You could do something like this:
NSMutableArray * imageArray;
imageArray = [[NSMutableArray alloc] init];
UIImage *oneImage = [UIImage imageNamed: #"33.png"];
[imagesArray addObject:oneImage];
[oneImage release];
//Add the remaining images, could probably turn this into a for loop
Alternatively, before you give that a shot, you could try to do [image release] after everything in your else statement that you provided.

Related

UIImagePickerControllerOriginalImage received memory warning and getting crash

I have a UICollectionView and a bar button at top right(CameraViewController1 : UICollectionViewController).The flow is when I take a picture it moves to a new view controller where the image can be cropped.User has two option Use and Cancel after choosing any of this option it gets back the image to the collection view and it gets arranged like cells.I want to take many photos.But I can take up to 3 pictures only where as the app crashes immediately and shows a message "App terminated due to memory pressure".But the worst part is when I tested the same app in iPhone 5 running iOS 7 the crash wasn't happen.When I test the same in iPhone 4 running iOS 7 it gets crashed and produce received memory warning.
Here my code
- (IBAction)TakeaPhoto:(id)sender {
[[UIApplication sharedApplication]setStatusBarHidden:FALSE withAnimation:NO];
gallery=0;
picker1 = [[UIImagePickerController alloc] init];
picker1.delegate = self;
self.resizeableCropArea =YES;
self.cropSize=CGSizeMake(300,350);
//picker1.allowsEditing = YES;
picker1.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker1 animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:NULL];
UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage];
image_cap = [self imageTemp:image scaledToSize:CGSizeMake(320, 370)];
dataTemp = UIImageJPEGRepresentation(image,0.0);
CropViewController *cropController = [[CropViewController alloc] init];
cropController.sourceImage = [info objectForKey:UIImagePickerControllerOriginalImage];
Original_img = UIImageJPEGRepresentation(cropController.sourceImage,0.0);
[original_image addObject:[UIImage imageWithData:Original_img]]; //original_image Nsmutablearray
NSLog(#"source image=%#",cropController.sourceImage);
cropController.resizeableCropArea = self.resizeableCropArea;
cropController.cropSize = self.cropSize;
cropController.delegate = self;
Cancel_Image= cropController.sourceImage;
[self.navigationController pushViewController:cropController animated:YES];
}
#Ramanan R R, I m totally agree with the #Rushabh's comment..
You are allocating that UIImagePickerController for many more times, as TakeaPhoto method call you are allocating UIImagePickerConrtoller, it is not necessary to allocate that multiple times. It makes memory spoilage, thats why your app is going to terminate or crash..
Just allocate that one time in viewDidLoad, make sure one more thing that, do
UIImagePickerController as a strong property, because in past it took my whole day to solve issue...
Hope this will work for you and your app will run smoothly...:)

uiimagepickercontrolleroriginalimage memory waring

I have a collection view (UICollectionViewController subclass) where I placed a UIBarButtonItem named "Take a photo". When I tap the bar button item my camera opens & I take a photo. In my project after "Use Photo" from camera it will move to a crop view controller where I crop the image after selecting the image from my crop view the image gets placed here in my collection view the current controller. In crop view I have two buttons use and cancel.My problem is when I take oddly 2,3 or 4 I receive a memory warning in console then the app crashes with a alert "application terminated due to memory pressure". I've been using this code, when I use UIImagePickerControllerEditedImage there is no issue instead if I use UIImagePickerControllerOriginalImage I come across memory issue.
My problem is to provide a good quality image and this UIImagePickerControllerOriginalImage provides a good quality than UIImagePickerControllerEditedImage.I have to get rid of this memory issue and so I used this line [self dismissViewControllerAnimated:YES completion:NULL];but I couldn't able clear the memory warning.
- (IBAction)TakeaPhoto:(id)sender {
[[UIApplication sharedApplication]setStatusBarHidden:FALSE withAnimation:NO];
gallery=0;
picker1 = [[UIImagePickerController alloc] init];
picker1.delegate = self;
self.resizeableCropArea =YES;
self.cropSize=CGSizeMake(296, 350);
picker1.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker1 animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:
UIImagePickerControllerOriginalImage];
image_cap = [self imageTemp:image scaledToSize:CGSizeMake(320, 370)];
dataTemp = UIImageJPEGRepresentation(image,0.0);
CropViewController *cropController = [[CropViewController alloc] init];
cropController.sourceImage = [info objectForKey:UIImagePickerControllerOriginalImage];
Original_img = UIImageJPEGRepresentation(cropController.sourceImage,0.0);
[original_image addObject:[UIImage imageWithData:Original_img]];
NSLog(#"source image=%#",cropController.sourceImage);
cropController.resizeableCropArea = self.resizeableCropArea;
cropController.cropSize = self.cropSize;
cropController.delegate = self;
Cancel_Image= cropController.sourceImage;
[self dismissViewControllerAnimated:YES completion:NULL];
[self.navigationController
pushViewController:cropController animated:YES];
}
Maybe you should compress your JPEG images. For example if you need that your images have a size less than 70kb, you can use this code:
float compressionRate = 0.90; // Initial compression rate
float maxCompressionRate = 0.10; // Max compression rate
NSData *data = UIImageJPEGRepresentation(outputImage, compressionRate);
// Our limit of size is MAX_UPLOAD_SIZE (70000) and compressionRate is 0.03f
while ([data length] > MAX_UPLOAD_SIZE && compressionRate >= maxCompressionRate) {
compressionRate -= 0.03;
data = UIImageJPEGRepresentation(outputImage, compressionRate);
}
Note: you can edit MAX_UPLOAD_SIZE with you desired size in bytes.

App crashes when capturing lot of images

I am getting a memory warning and the app crashes.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[self.btnSelectImage setImage:image forState:UIControlStateNormal];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
[popOverSelectImage2 dismissPopoverAnimated:YES];
UIViewController *vc = [[UIViewController alloc]init];
vc.view = self.captionView;
[popOverSelectImage setPopoverContentSize:CGSizeMake(self.captionView.frame.size.width, self.captionView.frame.size.height) animated:NO];
popOverSelectImage.contentViewController = vc;
[vc release];
}
else
{
[self dismissModalViewControllerAnimated:YES];
}
self.imageToSave = image;
self.imagePicker = nil;
}
When you set an image on a button, although it is displayed at a smaller size, it is using the full image, which, if you are getting it from the camera library, is going to be reasonably big.
If you are using a lot of these images, then you are going to be using a lot of memory.
If you want to use lots of these images as button images, then you should create smaller images at the size you require and use these thumbnails instead of the full image. You'll use a lot less memory this way.

How can I make sure an instance is not deallocated?

In my app, I am loading images for UITableViewCells asynchronously like this:
-(void) loadImage:(NSString *)urlString cell:(UITableViewCell *)cell {
UIImageView *iv = cell.imageView;
UIImage *image = [imageCache objectForKey:urlString];
if(!image) {
NSURL *url = [NSURL URLWithString:urlString];
image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
if(image) {
[imageCache setObject:image forKey:urlString];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
iv.image = image;
[cell addSubview:iv];
});
}
When the tableview is refreshed before all of the images have finished loading, an exception is thrown on iv.image = image; because iv has been deallocated. What is the best way to make sure I never try to set an image for a deallocated cell? Is there some way to kill any lingering asynchronous loads when the tableview is reloaded?
I would implement this other way around. Try to get an image from cache when you are constructing the cell. If the image is not found trigger on asynchronous download and notify cell or controller (from main thread) that image was downloaded. You can use KVO to connect cells with images cache.

How to clean memory after UIImageView animation

Here is my code:
Header:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView *imageView;
NSMutableArray *arrayWithImages;
}
- (IBAction)startAnimation:(id)sender;
- (IBAction)cleanMemory:(id)sender;
#end
Implementation:
#import "ViewController.h"
#implementation ViewController
......
- (IBAction)startAnimation:(id)sender {
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
arrayWithImages = [[NSMutableArray alloc] initWithObjects:
[UIImage imageNamed:#"pic1"],
[UIImage imageNamed:#"pic2"],
[UIImage imageNamed:#"pic3"],
[UIImage imageNamed:#"pic4"],
[UIImage imageNamed:#"pic5"],
[UIImage imageNamed:#"pic6"],
[UIImage imageNamed:#"pic7"],
[UIImage imageNamed:#"pic8"],nil];
imageView.animationImages = arrayWithImages;
imageView.animationDuration = 3;
imageView.animationRepeatCount = 1;
[self.view addSubview:imageView];
[imageView startAnimating];
}
- (IBAction)cleanMemory:(id)sender {
[arrayWithImages removeAllObjects];
[arrayWithImages release];
arrayWithImages= nil;
[imageView removeFromSuperview];
[imageView release];
imageView = nil;
}
#end
I have ViewController and its view with two buttons. First button with startAnimation action, which creates UIImageView , NSMutableArray and starts animation on it. Second button with cleanMemory action , which clean all what i've created in startAnimation.
When i start Profile with Activity Monitor instrument, my program have 4 mb Real Mem, when i press startAnimation button it's changes to 16 mb Real Mem and after animation i press cleanMemory button, but it has same 16 mb Real Mem... Why? I wont to clean my memory to started value( 4 mb Real Mem). Please, can you explain, where i have problems?
UIImage imageNamed: caches the images and will release the memory on it's own schedule. If you do not want the caching, that is completely control the memory then load the image directly,not with UIImage imageNamed:.
From the Apple docs:
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.
You can use
+ (UIImage *)imageWithContentsOfFile:(NSString *)path
to load the image directly.
From the Apple docs:
This method does not cache the image object.
If even after using + (UIImage *)imageWithContentsOfFile:(NSString *)path you still don't get to free memory, tyr calling imageView.animationImages = nil;

Resources