简体   繁体   中英

How do you perform additional initialization after calling the designated initializer in Objective-C? (self = [self…)

Suppose I have a designated initializer that does some initialization as such:

- (id)initWithBlah:(NSString *)arg1 otherBlah:(NSArray *)arg2
{ 
    if (self = [super init])
    {
        ...
    }
    return self;
}

and I have another initializer that needs to call this, but then perform some other setup task:

- (id)initWithSomeOtherBlah:(void *)creativeArg
{
    // Is this right? It seems to compile and run as expected, but feels wrong
    self = [self initWithBlah:nil otherBlah:nil];
    if (self)
    {
        [self someProcessingForThisInitDependentOnSelfInit:creativeArg];
    }

    return self;
}

Since the test to make sure the return value is correct, should 'self' be used in this context? I'm wondering if this is even a valid combination of events. We have a situation where we have an initializer that needs to perform some additional setup after the designated initializer is ran.

I'm wondering if the correct approach is to shove this additional processing in the designated initializer..

Please let me know if more clarification is needed. I was trying to keep this simple. :)

Thanks!

A general rule of thumb that I follow is that the designated initializer is the initializer with the most parameters and the other initializers chain down to the designated initializer.

In your example you are not using creativeArg in your initWithSomeOtherBlah constructor. I am not sure if that was intentional or not.

With this approach you are being explicit with your intentions when creating an object instead of side effect programming.

For example:

@implementation BlaClass

- (id)initWithBlah:(NSString *)arg1 otherBlah:(NSArray *)arg2 creativeArg:(void *)arg3
{
    if (self = [super init])
    {
        self.arg1 = arg1;
        self.arg2 = arg2;
        self.arg3 = arg3;
        [self someProcessingForThisInitDependentOnSelfInit:arg3];
    }
    return self;
}


- (void)someProcessingForThisInitDependentOnSelfInit:(void *)creativeArg
{
    if(creativeArg == NULL) return; 


    //do creative stuff 
}

- (id)initWithSomeOtherBlah:(void *)arg
{
    return [self initWithBlah:nil otherBlah:nil creativeArg:arg];
}

 ...
 @end

If you need two initializers in your class which initialize the class somewhat differently, a good coding practice is to identify the setup tasks that both initializers need to perform them, and move them to a separate method. This way, you don't need to call one custom initializer inside another. Here is how you need to do it:

-(void) setupBlah
{.....}

- (id)initWithBlah:(NSString *)arg1 otherBlah:(NSArray *)arg2
{ 
    if (self =[super init])
      {
        [self setupBlah];
        //Do other initialization
            ....
       }
   return self;
}

- (id)initWithSomeOtherBlah:(void *)creativeArg
{


    if (self = [super init])
    {
        [self setupBlah];
        //Do other initialization
          .....
    }

    return self;
}

There is nothing wrong with calling another initializer from a non-designated initializer, see Apple's docs here .

In the case that I have two or more designated initializers (such as a view with initWithFrame: and initWithCoder: ), I have found myself to define a setUp method that I call from both initializers, which is just a shorter name for your someProcessingForThisInitDependentOnSelfInit method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM