Objective-C多个嵌套的initWith用于自定义类

时间:2012-12-21 19:02:09

标签: ios objective-c memory-leaks automatic-ref-counting

我对Objective-C很新,我有一个问题。

我创建了一个自定义类并尝试为初始化创建重载:

- (id)init
{
    if (self = [super init]) {
        [self setIsCurrentCar:NO];
    }
    return self;
}

-(id) initWithID:(NSInteger)id {
    if(self = [self init]) {
        [self setID:id];
    }
    return self;
}

-(id) initWithID:(NSInteger)id CarYear:(NSString *)year {
    if(self = [self initWithID:id]) {
        [self setCarYear:year];
    }
    return self;
}

让我们说一下,我称之为-(id) initWithIDCarYear方法。

我想知道上面的代码在结构上是正确的。

  • 在此代码中,self设置为3次。还有更好的吗? 解?
  • 此代码中是否有内存泄漏? (使用ARC)
  • 我是否必须始终检查if(self = ...)或它是否 冗余代码?

谢谢

@Edit 以下代码更好吗?

-(id) initWithID:(NSInteger)id CarYear:(NSString *)year {
    if (self = [super init]) {
        [self setIsCurrentCar:NO];
        [self setID:id];
        [self setCarYear:year];
    }
    return self;
}

4 个答案:

答案 0 :(得分:9)

虽然您的代码没问题,但我会按相反的顺序构建init-calls,其中最详细的是指定的初始化程序,而更通用的会弹出一些默认值:

-(id) initWithID:(NSInteger)id 
         CarYear:(NSString *)year 
{
    if(self = [super init]) {
        _year = year;
        _id = id;
    }
    return self;
}

-(id)initWithID:(NSInteger)id 
{
    return [self initWithID:id CarYear:@"unset"];
}

-(id)init 
{
    return [self initWithID:0];
}

如果调用一个更通用的初始化程序会产生非法状态,你可以抛出错误来禁止使用它。

我们假设,汽车需要有一个ID,但不是一年。可以使用initWithID但使用init会导致状态不一致,所以我们要强制不使用它:

-(id)init 
{
    [NSException raise:NSInternalInconsistencyException 
                format:@"You must use -initWithID: or -initWithID:CarYear:", NSStringFromSelector(_cmd)];
    return nil;
}

  
      
  • 在此代码中,self设置为3次。有更好的解决方案吗?
  •   

见上文

  
      
  • 此代码中是否有内存泄漏? (使用ARC)
  •   

不,一切都很好

  
      
  • 我是否必须检查是否(se​​lf = ...)或者它是冗余代码?
  •   

正如我向您展示的那样:您可以在链中调用不同的init方法。只是该链中的最后一个需要执行该操作。


-(id) initWithID:(NSInteger)id CarYear:(NSString *)year {
    if (self = [super init]) {
        [self setIsCurrentCar:NO];
        [self setID:id];
        [self setCarYear:year];
    }
    return self;
}

你不应该在init-methods see Apple's docs中使用set上的setter。

答案 1 :(得分:3)

  

我想知道上面的代码在结构上是正确的。

是。我没有看到任何问题。

  

在此代码中,self设置为3次。有更好的解决方案吗?

这很正常。我不打算改变它。

  

此代码中是否有内存泄漏? (使用ARC)

没有

  

我是否必须始终检查是否(se​​lf = ...)或它是多余的   码?

你不必须,但你肯定 。有关详细信息,请参阅this question

答案 2 :(得分:2)

看起来你有一个强制的初始化变量和两个有效的可选项。

我建议为ID和carYear实现init方法和两个@property()。这减少了初始化器的数量,并更好地反映了该类的使用合同。

答案 3 :(得分:1)

从我的小知识...... tried to create overloads for Initialization这个陈述不应该在这里使用。

通常overload表示同名多个参数,但是在obj-c中我们不遵循这个。在obj-c中,通过命名参数来伪造重载。

所以这里有3组不同的代码,每一组都被称为其他方法。并且你没有内存泄漏,因为你没有为同一个对象分配内存三次,而是你正在初始化它。