Reputation: 66012
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
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
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
Reputation: 50727
The default
will be whichever one you choose to call,
[awesome alloc] init];
[awesome alloc] initWithAppId:ID];
Upvotes: 0
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