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
@i开发者_C百科mplementation 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?
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.
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.
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;
}
精彩评论