7

I created a custom object in Objective-C. Now I want to create a custom initializer. The object has two properties, name and score. So my initializer is as follows:

- (id)initWithName:(NSString *)playerName {

    if ((self = [super init])) {
        self.name = [playerName retain];
        self.score = [NSNumber numberWithInt:0];
    }

    return self;
}

Am I using retain here properly? Or can I just make it something like self.name = playerName;?

Furthermore, assume I want another initializer, but keep the initWithName:playerName the designated initializer. How would I make the second initializer call the first?

And for the last question, I know I need to override the - (id)init method too. However, what do I do there? Just assign test properties incase the class was initialized with init only?

Thank you!

3 Answers 3

7

Am I using retain here properly?

No you are not. You should either use

self.name = playerName;

as you suggested, or (as recommended by Apple)

name = [playerName copy];

It is not recommended to use accessors in -init because subclasses might override them.

Also, note that as NSString implements NSCopying you should use a copy property, not a retain property.

Furthermore, assume I want another initializer, but keep the initWithName:playerName the designated initializer. How would I make the second initializer call the first?

Using -init as an example (because you must override the super class's designated initialiser if your designated initialiser is not the same)

-(id) init
{
    return [self initWithName: @"Some default value"];
}
Sign up to request clarification or add additional context in comments.

2 Comments

Regarding NSString implementing NSCopying, so @property (nonatomic, retain) NSString ... would be wrong? I should substitute retain with copy? If so, then I should not release it in dealloc correct?
@Nayefc: @property (copy) NSString* is right for a NSString property (nonatomic is optional of course). You still need to release it in dealloc because you own objects obtained with copy.
2

you could keep self.name = playerName; if you have declared name as retained property in .h class and have also @synthesized in .m file.

For the initialization you could put the belwo two line of code in separate method.

-(void) initializeWithName:(NSString*) aName withNumber:(int) aNumber
{
  self.name = aName;
  self.score = [NSNumber numberWithInt:aNumber];
}

Lets you have three Initialization method.

- (id)initWithName:(NSString *)playerName {

    if ((self = [super init])) {
      [self initializeWithName:playerName withNumber:0]
    }

    return self;
}


- (id)initWithNumber:(int*) aNumber {

    if ((self = [super init])) {
       [self initializeWithName:nil withNumber:aNumber]
    }

    return self;
}


- (id)init{

    if ((self = [super init])) {
        [self initializeWithName:nil withNumber:0]
    }

    return self;
}

Comments

-2

For what's it's worth to the rest of us newbies:

In normal languages, can simply define arguments when instantiating the class:

public final class MakeBed {

    private var foo:Object;
    public var bar:Array;

    public function MakeBed(_foo:Object, _bar:Array) {
        // Do stuff
        foo = _foo;
        bar = _bar;
    }

}

Then when we want to instantiate the class it's as simple as:

var myBeadMaker:MakeBed = new MakeBed({}, []);

In objc everything is backasswards.

You can create your custom initializer similar to:

// These @properties go into the header.h file
@property (nonatomic, retain) NSString *foo;
@property (nonatomic, retain) NSString *bar;

// This is in your implimentation.m file
- (id) initWithInfo:(NSObject*)foo withBar:(NSArray *)bar {
    _foo = foo;
    _bar = bar;
}

Objc automatically "synthesizes" the getters and setters and automatically creates a new variable "blindly" using the same _name _but _with _an _underscore in front when you do the @property thing -- it's magic -- bordering on the "almost too helpful" side of things.

Handy for non-newbies, but incredibly confusing for newbies -- just believe that the getter and setter is made and that a _new _var _is _available.

And the clincher that everyone forgets to mention...

When you want to instantiate the class with your custom initializer you do this:

MakeBed myBedMaker = [[MakeBed alloc] initWithInfo:*foo withBar:*bar];

5 Comments

that initWithInfo:withBar: method is really wrong. It doesn't call super and doesn't return anything!
You have defined foo and bar as strings but use assign an NSObject and an NSArray to them. (Also bad practice to use retain/strong for classes that have mutable subclasses (like strings and arrays for example))
[[MakeBed alloc] initWithInfo:*foo withBar:*bar] is also wrong. You pass the arguments as initWithInfo:foo withBar:bar. All these things are basic Objective-C.
-1. You really miss some basic concepts of the language to afford to do a comparative analysis with anything.
By the way, when you approach a language you should its basic construct first. "Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName." This is taken from Apple doc and it's pretty visible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.