Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C: is there a precise definition for an initializer?

Tags:

objective-c

I read here (Is there a convention for naming initializer method in objective-c?) that "according to Apple, initializer methods should always begin with the word 'init'".

But, what is an initializer?

I know what is the "designated initializer". You could define it recursively: it is the only method calling the designated initializer of super ; plus: the designated initializer of NSObject is init.

But, what is an initializer?

I am asking this question because I hesitate between two names for an instance method of the class IceCream :

  • - (id)initIceCreamWithFlavour:

  • - (id)iceCreamWithFlavour: ("called on alloc")

I feel that relatively to the naming conventions of ARC, both names are OK. (This is my main concern here. Comments are welcome.) Now that I ask the question, the solution (id)iceCreamWithFlavour: seems better.

But the question still holds: what is an initializer?

I would say: an initializer is a method you "call on alloc".

like image 336
Colas Avatar asked Feb 15 '14 08:02

Colas


3 Answers

I would use - (id)initWithFlavour:.

So you would have:

IceCream *iceCream = [[IceCream alloc] initWithFlavour:Chocolate];

which tell you everything you need to know at a glance about the class and the initialisation parameter purpose. Restating ice cream in the method name is superfluous.

As for what the init method is, it's just the initialiser for the class. It's purpose is to create a configured new instance. To setup the default values (with, as in this case, some overrides or specific settings).

From your other method naming attempt, you could have:

+ (id)iceCreamWithFlavour:

Note the plus instead of minus, so this is a class method. This would be a suitable name for a convenience method which calls alloc] initWithFlavour: and returns the new instance.

Incidentally, if we add more parameters, don't restate with:

IceCream *iceCream = [[IceCream alloc] initWithFlavour:Chocolate sprinkles:YES];
like image 116
Wain Avatar answered Nov 15 '22 23:11

Wain


Objective-C uses a 2 step creation process for objects.
The first step is memory allocation, and the second step is initialisation (which sets the initial state of an object):

MYIceCream* iceCream = [[MYIceCream alloc] initWithFlavor:@"Cherry"];

You can have multiple init methods for your classes, but you should have only one of them that sets the complete state for a new object. This is the designated initialiser (which usually takes the most parameters).
The MYIceCream class could have the following designated initialiser:

- (id)initWithFlavor:(NSString*)flavorName topping:(NSString*)toppingName
{
    self = [super init];
    if (self) 
    {
        _flavorName = flavorName;
        _toppingName = toppingName;
    }
    return self;
}

All other initialisers would just call the above method and provide defaults (or nil) for some parameters:

 - (id)initWithFlavor:(NSString*)flavorName
{
    return [self initWithFlavor:flavorName topping:kMYToppingChoclate];
}

You can also define methods, that combine allocation and initialisation. Those are called factory methods. They are defined as class methods (denoted with a + sign) and don't have an init prefix:

+ (id)iceCreamWithFlavor:(NSString*)flavorName;

The factory method would just call alloc and init in it's implementation:

+ (id)iceCreamWithFlavor:(NSString*)flavorName
{
    return [[MYIceCream alloc] initWithName:flavorName];
}

Apple has a good intro to initialisers in the Cocoa Core Competencies guide and another good read in the Objective-C Programming Guide.

like image 29
Thomas Zoechling Avatar answered Nov 15 '22 23:11

Thomas Zoechling


I would say: an initializer is a method you "call on alloc"

Thats partly true.

There are 3 types of "direct" initializers as far as i know :

[init] initializer (following [X alloc] call)

Initializers starting with "init" always follow an alloc call. I haven't seen any UIKit or Foundation Class being initialized like : [[NSArray alloc] arrayWithObject:] <- Does not exist like that.

Class - initializers

Class initializer create an object from a class scope without having called alloc before. The implementation of this method, however, would sure call an [[alloc] init] to create an object.

Example : [NSMutableArray arrayWithCapacity:]

Class initializers always start with the corresponding class name.

In your case :

[IceCream iceCreamWithFlavor:]

Initializers creating from existing object.

These are creating an object from an existing one. They 'copy' the existing object and alter some properties.

Example: UIColor *red = [UIColor redColor];

UIColor *thinRedColor = [red colorWithAlphaComponent:0.5];

They also start with their corresponding class name like the Class - initializers

If you look through the UIKit and Foundation classes, you will find that these patterns are used in every Class ( & Class - Cluster).

So to answer your question:

The "UIKit / Foundation" - way of naming your initializers would be :

When called after alloc:

- (instancetype)initWithFlavour:

When called on an existing object :

- (instancetype)iceCreamWithFlavourAlteredByValue:

When called on your Class-Object :

+ (instancetype)iceCreamWithFlavour:
like image 3
CodingMeSwiftly Avatar answered Nov 15 '22 21:11

CodingMeSwiftly