Reputation: 8109
UIImage API Reference Document:-
initWithContentsOfFile:
Initializes and returns the image object with the contents of the specified file.
- (id)initWithContentsOfFile:(NSString *)path
Parameters
path
The path to the file. This path should include the filename extension that identifies the type of the image data.
Return Value
An initialized UIImage object, or nil if the method could not find the file or initialize the image from its contents.
Considering this scenario, suppose I have a class, it could be extension of any class. Just took UIImage for example.
@interface myImage : UIImage
{
BOOL isDefaultSet;
}
-(id)initWithDefaultImage;
@end
@implementation myImage
-(id)initWithDefaultImage
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
idDefaultSet = YES;
return [self initWithContentsOfFile:path];
}
@end
//somewhere in other class:
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
myImage *myObject = [[myImage alloc] initWithDefaultImage];
UIImage *yourObject = [[UIImage alloc] initWithContentsOfFile:path];
now here in both cases,
"alloc" gives "retainCount+1"
and if
initWithDefaultImage/initWithContentsOfFile
returned nil due to some issue - lets say (invalid file path), this memory will be leaked as
myObject/yourObject
will be set to nil even though the allocation was made before init.
I have seen many implementations for extended classes/interfaces in this manner. I'm confused how memory is being handled here? can anyone share view on this?
Upvotes: 0
Views: 251
Reputation: 4623
You are right, sometimes people forget to handle this leak. The allocated memory needs to be released if we cannot proceed with the initialisation.
-(id)initWithDefaultImage
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
if (path != nil)
{
self = [super initWithContentsOfFile:path];
}
else // cannot proceed with init
{
[self release];
self = nil;
}
return self;
}
Upvotes: 0
Reputation: 28572
if [super init] returns nil, nil is returned. so the control returns from method and if (someInitializingFailed) block will never be executed and memory will be leaked as alloc is already executed before calling "initWithFoo"
if [super init]
returns nil
, super's init
has already cleaned after itself and released the memory allocated by alloc
.
From Handling Initialization Failure:
You should call the release method on self only at the point of failure. If you get nil back from an invocation of the superclass’s initializer, you should not also call release.
Upvotes: 1
Reputation: 92424
Usually the corresponding initializer releases self
(the new object) before returning nil
, as in:
- (id)initWithFoo
{
self = [super init];
if (!self) return nil;
if (someInitializingFailed) {
[self release];
return nil;
}
return self;
}
You can assume that -[UIImage initWithContentsOfFile:]
is implementing the same pattern. So unless Instruments does tell you there's a leak you don't need to do any special handling in your case.
Upvotes: 1