Adam
Adam

Reputation: 9049

Using UIImageView without being a memory hog?

UIImageView *mooshinLogo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mooshin.png"]];

I'm not sure if im instantiating my image correctly because i've been reading that imageNamed will not be emptied from the cache and should only be used for buttons and small icons. What about background images, and image galleries?

How do I implement UIImageView the right way?

Upvotes: 1

Views: 223

Answers (4)

smcdrc
smcdrc

Reputation: 1691

Others above are right about imageNamed keeps a cache of these images. This is especially true when using NIB files. Releasing a Viewcontroller with ImageViews on them doesn't directly release the associated images.

I had an app that had lots of images with lots of pages in a navigation controller. Eventually it would crash when only using imageNamed method. So, I now use (found here on SO) and over:

+ (UIImage *)imageNamed:(NSString *)name {
    //NSLog(@"ImageNamed: %@", name);
    return [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:nil]];
}

Now I can control when I want to remove an image and and make it actually clear from memory. The aforementioned app, I would actually load the images on viewDidLoad and remove them on viewDidDisappear. So, when I was 10-15 pages deep in the NavController, I could keep memory down.

Upvotes: 0

Evgeny Shurakov
Evgeny Shurakov

Reputation: 6082

imageNamed: method caches images that you load. In case of low memory conditions or memory warning that cache will be emptied.

If you want to show images in gallery it is better to use imageWithContentsOfFile: method as it doesn't cache the data.

In case of very big images you should use CATiledLayer to display your image using tiles.

Upvotes: 2

wjl
wjl

Reputation: 7351

[UIImage imageNamed:(NSString *)imageName] is an autorelease convenience constructor. This means that it's retain count is increased when you initialize it and decreased at the end of the runloop. You could make 100 of them and they'd vanish from memory a few seconds later, unless they're retained by something else. By passing it to the UIImageView, the UIImageView will retain it and it will stay in memory only until the UIImageView is done with it, so you're doing that correctly, unless you're referring to the OS caching the image in "inactive" RAM. It may do that behind the scenes (and will know when to get rid of it), but you're certainly handling the object's lifecycle correctly. Since you're using the [[Class alloc] init...] way to construct your UIImageView, make sure you later call [mooshinLogo release] or [mooshinLogo autorelease].

(Please just ignore this if you already know.) Objective-C (at least, for iOS development) is a reference counted language. All objects start out with a reference count, or retain count, of 1, from the time they are alloc'd. From there, they can be retained ( [id retain] ), released ( [id release] ), or marked to be released at the end of the runloop ([id autorelease] ). Once the count is zero, they will be dealloc'd, but you should never concern yourself with it's actual retain count and only use objects you own (or are retaining).

When in doubt, you can check with Clang's Static Analyzer. It's finds probably 75% of the your leaks, and I've only had a handful of false positives. Either Build & Analyze, or Cmd+Shift+B.

Upvotes: 0

Mundi
Mundi

Reputation: 80265

No worries! The method imageNamed returns an autoreleased object, and it will do what you call "be emptied from cache" (i.e. its memory will be released) when it is not needed any more.

Upvotes: 0

Related Questions