I have an NSMutableArray that contains images. I then have an image view that displays images from that array. However, I am getting a big memory leak each time it loads the image view. I am not sure how to correct that. I am using ARC in Xcode 5.0.2.
_image1 = [UIImage imageNamed:#"FirstImage.png"];
imagearray = [[NSMutableArray alloc] init];
[imagearray addObject:_image1];
_imageview1 setImage:[imagearray objectAtIndex:0]];
The memory leak issue might be due to the UIImage not getting nil. For that, you have to initialize UIImage with alloc and after adding it to the array, make it nil. You can prevent you memory leak in this way:
UIImage *image1 =[[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"FirstImage" ofType:#"png"]];
[imagearray addObject:image1];
_imageview1 setImage:[imagearray objectAtIndex:0]];
image1 =nil;
Please let me kniw if it works. Thanks :)
From apple doc:
+ (UIImage)imageNamed: 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.
If you have an image file that will only be displayed once and wish to
ensure that it does not get added to the system’s cache, you should
instead create your image using imageWithContentsOfFile:. This will
keep your single-use image out of the system image cache, potentially
improving the memory use characteristics of your app.
So as a suggestion, if you replace the imageNamed: with imageWithContentsOfFile: to avoid caching, your memory footprint should improve
Related
I am getting memory warning when loading large images, i have to cache the images also so that if the user will scroll up that image should be present. I am using SDWebImage Library.
cell!.productImageView?.sd_setImageWithURL(url)
According to your scenario I have two suggestions:
1. Generally recommended is that we can upload small size images on server so that we can avoid memory problems. A thumbnail or a small dimension sized image is considered if we are showing the images in a UITableView.However we can show larger image when we tap on a certain small image in UITableView and go to a detail view controller.
2. Secondly you can download the images and resize them and then use NSCache class to cache them rather using SDWebImage. As in your case imageWithContentsOfFile can't be used because you are downloading the images from some URL.However after download you can use imageWithContentsOfFile or you can resize images and use your own NSCache.
What are you using for display image on image view .UIImage imageNamed is maintain cache itself.
Please use below code.
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageName" ofType:#"png"]];
This will helpful to you for manage memory consumptions.
Try this code.
NSString *thumbnailImage = objectname.thumbnailUrl;
[cell.productImageView sd_setImageWithURL:[NSURL URLWithString:thumbnailImage]];
My project is having image sharing functionality. In this functionality my app asks the user from which library you want to share.
I wrote below code to assign image, retrieved from Default library/Custom library.
Device default library
imgVwMediaFile.image = [UIImage imageWithCGImage:[asset thumbnail]; //(ALAsset *)asset
Custom library (images are at Documents/image/user)
imgVwMediaFile.image = [UIImage imageWithContentsOfFile:path];
//(NSString*)path
App displyas this images in collection view having custom cell.
When i select app custom library then images are retrieves from Documents directory ,but imagewithcontentofFile cosuming around 90 to 100 Mb memory.
In other case when i select app default libray, it is not cosuming more then 8 or 10 Mb memory.
I tried diffrent code from stack Q/A for custom library, but still memory issue is there.
-1-
CGImageRef iref = [[UIImage imageNamed:asset] CGImage] ;
imgVwMediaFile.image=[UIImage imageWithCGImage:iref];
iref=nil
-2-
NSData *imageData = [[NSData alloc] initWithContentsOfFile:path];
imgVwMediaFile.image=[UIImage imageWithData:imageData];
imageData=nil
-3-
imgVwMediaFile.image=[UIImage imageNamed:path];
So please guide me that, how can i load images from document dir ?
What are the best way to load images from document dir without increasing memory load ?
The problem is that yhe images you have saved to disk are large, so loading lots of the, to display in a collection takes a lot of memory. You use thumbnails from the built in library so you see a different result.
Ideally you would save a folder of thumbnails in your custom library and display those, then, when an image is selected, get the corresponding full size image to use (this is the approach basically all photo libraries use). Alternatively you can resize the images on-the-fly, but your scrolling is basically guaranteed to suck.
UIImage *img = [UIImage imageWithContentsOfFile:path];
In my iPad app at one moment I load 100 images from Photo Stream using ALAsset and following code:
ALAsset *asset = [assets objectAtIndex:[sender tag]];
ALAssetRepresentation *representation = [asset defaultRepresentation];
UIImage *image = [[UIImage alloc] initWithCGImage:[representation fullScreenImage]
scale:1.0f
orientation:0];
And everything works perfectly. But when I cache it to the file system as JPEG files, and then load them again with UIImage *image = [UIImage imageWithContentsOfFile:fullPath], application crashes with Memory Warning, and I can see in the profiler that it really uses a lot of RAM.
Why is this happening?
One thing,
When you are loading the image from gallery, why not store the AssetURL, instead of the UIImage; that should take less space and increase speed.
When you need to show, use the thumbnail representation, perhaps?
Ok, it was my bad. I found the problem, and it comes out that I have memory problems in any case. ALAsset and imageWithContentsOfFile are working exactly the same.
Now I will try to find the way to reduce each image's size.
I have an app that uses UIImage objects. Up to this point, I've been using image objects initialized using something like this:
UIImage *image = [UIImage imageNamed:imageName];
using an image in my app bundle. I've been adding functionality to allow users to use imagery from the camera or their library using UIImagePickerController. These images, obviously, can't be in my app bundle, so I initialize the UIImage object a different way:
UIImage *image = [UIImage imageWithContentsOfFile:pathToFile];
This is done after first resizing the image to a size similar to the other files in my app bundle, in both pixel dimensions and total bytes, both using Jpeg format (interestingly, PNG was much slower, even for the same file size). In other words, the file pointed to by pathToFile is a file of similar size as an image in the bundle (pixel dimensions match, and compression was chosen so byte count was similar).
The app goes through a loop making small pieces from the original image, among other things that are not relevant to this post. My issue is that going through the loop using an image created the second way takes much longer than using an image created the first way.
I realize the first method caches the image, but I don't think that's relevant, unless I'm not understanding how the caching works. If it is the relevant factor, how can I add caching to the second method?
The relevant portion of code that is causing the bottleneck is this:
[image drawInRect:self.imageSquare];
Here, self is a subclass of UIImageView. Its property imageSquare is simply a CGRect defining what gets drawn. This portion is the same for both methods. So why is the second method so much slower with similar sized UIImage object?
Is there something I could be doing differently to optimize this process?
EDIT: I change access to the image in the bundle to imageWithContentsOfFile and the time to perform the loop changed from about 4 seconds to just over a minute. So it's looking like I need to find some way to do caching like imageNamed does, but with non-bundled files.
UIImage imageNamed doesn't simply cache the image. It caches an uncompressed image. The extra time spent was not caused by reading from local storage to RAM but by decompressing the image.
The solution was to create a new uncompressed UIImage object and use it for the time sensitive portion of the code. The uncompressed object is discarded when that section of code is complete. For completeness, here is a copy of the class method to return an uncompressed UIImage object from a compressed one, thanks to another thread. Note that this assumes data is in CGImage. That is not always true for UIImage objects.
+(UIImage *)decompressedImage:(UIImage *)compressedImage
{
CGImageRef originalImage = compressedImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
return decompressedImage;
}
Probably I'm gonna ask the same question which was asked by other person (But it has no responses): Speed up first UIImageView animation (force cache the images)
But, My short question is:
I have 60 images in resources, in timeinterval loop I'm gonna animate that images, each time setting to UIImageView.image the n'th image from resouce.
The problem is: first animation is bad! When I loop all images again in same UIImageView, animation is perfect. Can we pre cache images in UIImageView?
EDIT: Or maybe we can make some tricks, to make animation smooth?
The method
[UIImage imageNamed:#""]
caches the image. The UIImageView doesn't. I had a problem in an app with a lot of images that was crashing due to low memory.
To fix if I changed to [UIImage imageWithContentsOfFile:#""] that does not caches the image.
To pre-cache the image you can simply call [UIImage imageNamed:#""] for all images you want in the init method. But if you receive a memory warning the images gonna be deallocated.
UIImageView does not cache the image, as [UIImage imageNamed:#""] does. Unfortunately, if you have a lot of images, imageNamed will crash your application because it runs out of memory.
You can pre-load all of the images in an NSArray using [UIImage imageWithContensOfFile:#""].
Once you have the array, you can do what you want!
No, UIImageView does not cache images. image property declared as retain, so when you set new image, then imageView send release message to old image and retain to new one.
The easiest way to animate UIImageView is to set array of images to property animationImages and call startAnimating method
imageView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:#"1.png"], ..., nil];
imageView.animationDuration = 2.0f;
[imageView startAnimating];