Alex
Alex

Reputation: 66012

objective-c default init method for class?

I have two differing methods for initializing my objective-c class. One is the default, and one takes a configuration parameter. Now, I'm pretty green when it comes to objective-c, but I've implemented these methods and I'm wondering if there's a better (more correct/in good style) way to handle initialization than the way I have done it. Meaning, did I write these initialization functions in accordance with standards and good style? It just doesn't feel right to check for the existence of selfPtr and then return based on that.

Below are my class header and implementation files. Also, if you spot anything else that is wrong or evil, please let me know. I am a C++/Javascript developer who is learning objective-c as hobby and would appreciate any tips that you could offer.

#import <Cocoa/Cocoa.h>

// class for raising events and parsing returned directives

@interface awesome : NSObject {
 // silence is golden. Actually properties are golden. Hence this emptiness.
}

// properties
@property (retain) SBJsonParser* parser;
@property (retain) NSString* eventDomain;
@property (retain) NSString* appid

// constructors
-(id) init;
-(id) initWithAppId:(id) input;

// destructor
-(void) dealloc;


@end

#import "awesome.h"
#import "JSON.h"


@implementation awesome



- (id) init {
 if (self = [super init]) {
  // if init is called directly, just pass nil to AppId contructor variant
  id selfPtr = [self initWithAppId:nil];
 }

 if (selfPtr) {
  return selfPtr;
 } else {
  return self;
 }
}

- (id) initWithAppId:(id) input {
 if (self = [super init]) {
  if (input = nil) {
   input = [[NSString alloc] initWithString:@"a369x123"];
  }
  [self setAppid:input];
  [self setEventDomain:[[NSString alloc] initWithString:@"desktop"]];
 }
 return self;
}

// property synthesis
@synthesize parser;
@synthesize appid;
@synthesize eventDomain;

// destructor
- (void) dealloc {
 self.parser = nil;
 self.appid = nil;
 self.eventDomain = nil;
 [super dealloc];
}

@end

Thanks!

Upvotes: 8

Views: 15730

Answers (4)

ughoavgfhw
ughoavgfhw

Reputation: 39925

Your init method should call the preferred initializer, initWithAppId:, instead of the super implementation. Then the initWithAppId calls the super implementation, as it does. Also, in initWithAppId:, you have if(input = nil), which will always set input to nil and evaluate to YES. Here are the proper implementations.

- (id)init {
    return [self initWithAppId:nil];
}
- (id)initWithAppId:(id)input {
    if((self = [super init])) {
        if(input == nil) input = @"a369x123";
        self.appid = input;
        self.eventDomain = @"desktop";
    }
    return self;
}

Upvotes: 1

d11wtq
d11wtq

Reputation: 35318

When one initializer simply performs the more complex initializer with some default parameters, call it as such:

-(id)init {
  return [self initWithAppID:nil];
}

-(id)initWithAppID:(id)input {
  if (self = [super init]) {
    /* perform your post-initialization logic here */
  }
  return self;
}

Usually you try to make one of the initializers the "designated initializer", meaning it's the one that always gets invoked. In this case that's -initWithAppID:.

Upvotes: 15

WrightsCS
WrightsCS

Reputation: 50727

The default will be whichever one you choose to call,

[awesome alloc] init];
[awesome alloc] initWithAppId:ID];

Upvotes: 0

jer
jer

Reputation: 20236

To be honest, I see this as a moot point. Your second initialization method makes no sense when receiving a nil argument (plus you have a logic problem in your conditional checking if input is nil). What I would do in this case, is provide one initialization method, and two factory class methods which act in the usual way: Return autoreleased instances, and in one of them, provide your default value.

For instance, declare a class method:

+ (awesome*)awesome;
+ (awesome*)awesomeWithAppId:(id)foo;

and in your implementation for +awesome for instance, write it like this:

+ (awesome*)awesome
{
    return [[[awesome alloc] initWithAppId:@"a369x123"] autorelease];
}

And likewise, in your awesomeWithAppId: something like this:

+ (awesome*)awesomeWithAppId:(id)foo
{
    return [[[awesome alloc] initWithAppId:foo] autorelease];
}

Then again, this may just be me.

Upvotes: 0

Related Questions