0
votes

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?

3
I propose to stick to the convention and have your classes start with uppercase characters. You'll make your life easier (and if you work with other people, you'll avoid being insulted and beaten ;-)DarkDust
dear DarkDust.. I'm just having a discussion on the issue. please dont be so harsh..!Saurabh Passolia
i think DarkDust was making a joke, that's all. DarkDust is correct, though, as I've learned the hard way, that classes should be capitalized, ivars and methods start with lowercase.johnbakers

3 Answers

1
votes

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.

1
votes

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.

0
votes

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;
}