Sabobin
Sabobin

Reputation: 4276

Do I need to allocate NSStrings passed in as parameters to a custom initialization method?

Please consider the following two initialization methods.

The first method simply passes the value of the parameters to their respective NSString properties, but the second allocates the properties and then initializes them using the initWithString: method. Is the allocation in the latter example necessary?

Thanks in advance.

-(id)initWithTitle:(NSString *)theTitle muscleGroup:(NSString *)theMuscleGroup equipment:(NSString *)theEquipment {
    if((self = [super init])){  
        title = theTitle; 
        muscleGroup = theMuscleGroup; 
        equipment = theEquipment; 
    }
    return self; 
}

-(id)initWithTitle2:(NSString *)theTitle muscleGroup:(NSString *)theMuscleGroup equipment:(NSString *)theEquipment {
    if((self = [super init])){  
        title = [[NSString alloc] initWithString:theTitle]; 
        muscleGroup = [[NSString alloc] initWithString:theMuscleGroup]; 
        equipment = [[NSString alloc] initWithString:theEquipment];  
    }
    return self; 
}

Upvotes: 2

Views: 370

Answers (3)

Warren Burton
Warren Burton

Reputation: 17382

Example 1 will assign the pointers. It makes no attempt to retain the objects and is vulnerable to something outside changing the content of the objects.

It could work depending on how the arguments are constructed in the first place;

Example 2 will copy the string objects and retain them. As long as you release in the dealloc then its the preferable method.

FWIW

title = [theTitle copy];

or

title = [[NSString stringWithString:theTitle] retain];

are equally good in Ex 2

Upvotes: 2

Tom Jefferys
Tom Jefferys

Reputation: 13310

Parameter objects don't get copied when you pass them in. So your first example may not always work, it depends how you've initialized your strings.

The following is safer (although remember to release the objects in your dealloc method):

-(id)initWithTitle:(NSString *)theTitle muscleGroup:(NSString *)theMuscleGroup equipment:(NSString *)theEquipment {
    if((self = [super init])){  
        title = [theTitle retain]; 
        muscleGroup = [theMuscleGroup retain]; 
        equipment = [theEquipment retain]; 
    }
    return self; 
}

Upvotes: 2

alexantd
alexantd

Reputation: 3605

The first example is not safe because you are not taking ownership of the strings, so your program will get all crashy if they are later released elsewhere. The second example fixes that problem and will work perfectly well, but is more concisely written thusly:

-(id)initWithTitle2:(NSString *)theTitle muscleGroup:(NSString *)theMuscleGroup equipment:(NSString *)theEquipment {
    if((self = [super init])){  
        title = [theTitle copy]; 
        muscleGroup = [theMuscleGroup copy]; 
        equipment = [theEquipment copy];  
    }
    return self; 
}

NSString gives you a copy constructor (-initWithString:), which enables you to do what you are doing in #2, but not all classes do. copy requires the class to implement the NSCopying protocol, but is more conformant with the way a Cocoa API developer would expect to be able to copy objects.

Upvotes: 5

Related Questions