Reputation: 604
I currently working on a personal project in iOS7, and I must display several images on a Galarie scroll view. To do this I created a UIImage
then I insert it in a UIImageView
. I stock all my UIImageView
in a NSMutableArray
.
I show all the pictures on the UIScrollView
.
With the test I could perform, the memory used can go over 500 MB.
How can I optimize memory? How the camera base application it happens to you to display over 1000 photos?
Thank you in advance. Cordially.
Upvotes: 1
Views: 534
Reputation: 3081
Simple solution is that to save original image to directory and assign resized image to scrollview. This solution will make you able to add greater number of images to scrollview with minimal usage of memory. Here is the sample code
-(IBAction)selectImageBtnClicked:(id)sender {
UIImagePickerController * picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self presentViewController:picker animated:YES completion:nil]; [picker release]; }
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissViewControllerAnimated:YES completion:nil]; [[picker parentViewController] dismissViewControllerAnimated:YES
completion:nil];
UIImage *pTakenImage = [info objectForKey:UIImagePickerControllerEditedImage]; if (!pTakenImage) pTakenImage = [info objectForKey:UIImagePickerControllerOriginalImage]; [self performSelectorOnMainThread:@selector(proceedFURTHER:)
withObject:pTakenImage waitUntilDone:NO]; }
-(void) proceedFURTHER : (UIImage*)pTakenImage { UIImage *pResizedImage = [self resizeImageToMaxSize:640.0 anImage:pTakenImage];
[self saveOriginalImageToDir:pTakenImage]; //add pResizedImage to your scrolview here [self.navigationController popViewControllerAnimated:YES]; }
-(UIImage*)resizeImageToMaxSize:(CGFloat)max anImage:(UIImage*)anImage {
NSData * imgData = UIImageJPEGRepresentation(anImage, 1); CGImageSourceRef imageSource =
CGImageSourceCreateWithData((CFDataRef)imgData, NULL); if (!imageSource) return nil;
CFDictionaryRef options =
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
(id)[NSNumber numberWithFloat:max], (id)kCGImageSourceThumbnailMaxPixelSize, nil];
CGImageRef imgRef =
CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options);
UIImage* scaled = [UIImage imageWithCGImage:imgRef]; CGImageRelease(imgRef); CFRelease(imageSource); return scaled;
}
-(NSString*)getOriginalImageDirectoryPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; NSString *filePath =
[documentsPath stringByAppendingPathComponent:@"scaledimage.png"];
return filePath; }
-(void) saveOriginalImageToDir :(UIImage*)image {
NSString *filePath = [self getOriginalImageDirectoryPath]; if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; NSData *data = UIImagePNGRepresentation(image); [data writeToFile:filePath atomically:YES]; data = nil; }
Upvotes: 0
Reputation: 27598
I ran into this exact same problem couple of years ago when I used full size pictures in my UIImageViews. My app kept running out of memory on actual iPhone 4. For some reason it worked fine on iPhone simulator.
You must reduce your original images down using "UIImage+Resize" to show preview images in your UIScrollView. When user clicks on one of the images you can then show them a bigger/full version.
CGSize buttonSize = CGSizeMake(100, 100);
UIImage * newImage = [[UIImage alloc] initWithContentsOfFile: pathToImage];
if(newImage)
{
// this "resizedimage" image is what you want to pass to setImage
UIImage * resizedImage = [newImage resizedImage: buttonSize interpolationQuality: kCGInterpolationLow];
}
Upvotes: 0
Reputation: 109
UICollectionView is more appropriate for your problem!
UICollectionView is like UITableView, only loads cells displayed on screen.
UICollectionView is a scrollview, but with memory management.
Upvotes: 1
Reputation: 6211
You need to set up lazy loading based on the scrollview location. Load only three times the visible screen (or less, depending on memory need) and implement the UIScrollViewDelegate function scrollviewDidScroll:
to listen for scrolling events.
Inside scrollViewDidScroll you are going to want to search your array of images (it should be an array of locations and file names for best memory relief). If the scrollview is getting close to your image location then load it and add it to screen. If something was already on screen but is now far enough to be off screen and unloaded then remove it from the scrollview and release the object (or better, re-use it for the next image load).
Look into PDFKitten. They do lazy loading of PDF Pages. Your Images could be implemented the exact same way.
Upvotes: 1