Reputation: 1806
I am working on an app that imports photos from photo library. While importing the photos its using up alot of memory and after importing 160 photos it crashes.
I dont know why is this happening. Any help would be much appreciated.
Here is my code
- (void)agImagePickerController:(AGImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info{
[pickerView dismissViewControllerAnimated:YES completion:nil];
[self.navigationItem setHidesBackButton:YES];
[self.navigationItem.rightBarButtonItem setEnabled:NO];
MBProgressHUD * hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText=@"Importing Your Photo(s)";
// USING GRAND CENTRAL DISPATCH
firstQueue=dispatch_queue_create("com.import.photos", nil);
dispatch_async(firstQueue, ^{
[self beingBackgroundUpdateTask];
// Open connection
//[albumObject openDB];
// Start the loop from here ******************************************************
int j=0;
for(j=0;j<info.count;j++){
// update the hud label
hud.labelText=[[NSString alloc] initWithFormat:@"Importing %i of %i",j+1, [info count]];
// Create new image from returned array
ALAssetRepresentation *rep = [[info objectAtIndex: j] defaultRepresentation];
UIImage * image = [UIImage imageWithCGImage:[rep fullScreenImage]];
//rep=nil;
// resize the image for the thumbnail and save it in new image
UIImage *newImage=[image resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(75, 75) interpolationQuality:kCGInterpolationDefault];
NSDate *date = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateFormat:@"DD_MM_YY_HH_mm_ss"];
NSString *dateString = [dateFormat stringFromDate:date];
int random=rand();
// create new file names
NSString *fileName=[[NSString alloc] initWithFormat:@"%d%@",random,dateString];
NSString *s_fileName=[[NSString alloc] initWithFormat:@"small_%d%@",random,dateString];
// where to save this image
NSString *imagePath=[self.documentsDirectory stringByAppendingPathComponent:fileName];
NSString *s_imagePath=[self.documentsDirectory stringByAppendingPathComponent:s_fileName];
NSLog(@"type: %@",[rep.url pathExtension]);
if ([[rep.url pathExtension] isEqualToString:@"JPG"]) {
// its jpg
NSData *rawImage=UIImageJPEGRepresentation(image, 1.0);
NSData *thumb=UIImageJPEGRepresentation(newImage, 1.0);
image=nil;
newImage=nil;
date=nil;
dateFormat=nil;
dateString=nil;
random=nil;
// Create the images
[rawImage writeToFile:imagePath atomically:YES];
[thumb writeToFile:s_imagePath atomically:YES];
imagePath=nil;
s_imagePath=nil;
rawImage=nil;
thumb=nil;
}
if ([[rep.url pathExtension] isEqualToString:@"PNG"]) {
// its PNG
// save it in NSData to it can be saved in the directory
NSData *rawImage=UIImagePNGRepresentation(image);
NSData *thumb=UIImagePNGRepresentation(newImage);
image=nil;
newImage=nil;
date=nil;
dateFormat=nil;
dateString=nil;
random=nil;
// Create the images
[rawImage writeToFile:imagePath atomically:YES];
[thumb writeToFile:s_imagePath atomically:YES];
imagePath=nil;
s_imagePath=nil;
rawImage=nil;
thumb=nil;
}
// Now save it to database
[albumObject savePhoto:fileName toFID:PassedID toName:s_fileName albumName:singletonObj.currentAlbum photosName:singletonObj.currentPhotos];
[display_photos addObject:[MWPhoto photoWithFilePath:[self.documentsDirectory stringByAppendingPathComponent:fileName]]];
UIImage *img=[UIImage imageWithContentsOfFile:[self.documentsDirectory stringByAppendingPathComponent:s_fileName]];
[collection_photos addObject:img];
img=nil;
NSArray *pObj=[[NSArray alloc] initWithObjects:fileName,s_fileName, nil];
[photos addObject:pObj];
pObj=nil;
fileName=nil;
s_fileName=nil;
} j=nil;
// Update the album photo count to reflect the changes
[albumObject updateAlbumCount:PassedID photocount:[photos count] albumName:singletonObj.currentAlbum];
photos=[albumObject getPhotos:PassedID photosName:singletonObj.currentPhotos];
// End the loop here ***************************************************************
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self.navigationItem setHidesBackButton:NO];
[self.navigationItem.rightBarButtonItem setEnabled:YES];
});
});
}
Upvotes: 2
Views: 1777
Reputation: 535557
In the loop, a lot of extra objects are being generated, and they are not released until the whole loop is finished. But it never finishes because the extra objects just keep piling up until you run out of memory. The first line of defence is to wrap the interior of the loop in an @autoreleasepool
block.
For an example, look at this section of my book: http://www.apeth.com/iOSBook/ch12.html#_autorelease Scroll down to the bottom of that section.
for /* loop iterator goes here */ {
@autoreleasepool {
// everything inside the for loop goes here
}
}
EDIT: I have another suggestion: Are you ending up with an array of images or something like that? I can't quite tell. If so, then instead of storing images in memory as the ultimate result of all this, keep the images on disk and store their URLs or file paths instead. That way you only fetch the images when you need them. Images take a lot of room in memory, and it goes up exponentially with the size.
Upvotes: 4