从[[class alloc] init]返回nil被认为是好习惯吗?

时间:2010-08-12 17:53:48

标签: cocoa idioms

这是Objective-C中常见的习语。

我只看到[[NSImage alloc] initWithContentsOfFile:str]上使用它,它总是让我觉得存在内存泄漏,因为我调用了alloc而且口头禅是: “调用alloc,你必须调用release” - 除非是你不需要的情况之一。

3 个答案:

答案 0 :(得分:6)

在初始化对象时指示错误是一种常见的习惯用法。你是对的,但必须释放分配的实例。所以模式将是

- (id)init
{
  self = [super init];
  if(self != nil) {
    //... do init
    if(errorInInit) {
      [self release];
      return nil;
    }
  }

  return self;
}

答案 1 :(得分:0)

有关init方法的更多问题和解答,请参阅using alloc and init

也接受args(例如:initWithXxx:(Xxx*)x,例如NSString的{​​{1}})的init方法可以返回initWithBytes:而无需调用nil if(例如,它不喜欢它收到的arg。 init方法必须像任何方法一样管理内存。只是init有一些不寻常的行为,即返回其[super init]或返回其他对象,因为它选择了。一般来说,这并不是很多。

答案 2 :(得分:0)

关于这个主题的两个后续问题,我还没有看到明确的答案 - 现在在自己的问题中重复,Followup to returning nil from a [[class alloc] init]

1:如果init在调用super之前失败了某些先决条件,该怎么办?例如,假设在这个initWithStuff:方法中传递nil或者通常没有值传递给initWithValue:绝对失败,我们肯定想要返回nil。

- (id)initWithStuff:(Stuff *)inStuff {
  if (!inStuff || ![inStuff hasValidValue])
  {
    // can't proceed to call initWithValue: because we have no value
    // so do what?
    return nil;
  }
  NSInteger value = [inStuff integerValue];
  return [super initWithValue:value];
}

也许一个更清晰的例子是,如果我们包装的指定初始化方法接受一个对象指针,并且如果它传递了nil则抛出异常。我们肯定需要将导致异常的init调用短路。

我的猜测:以任何可能的方式初始化,然后在返回nil之前释放self。如有必要,请调用裸init或任何其他初始化程序,以便在释放之前完成将self置于已知状态。

  // can't proceed to call super's initWithValue: because we have no value
  // so do what? do this:
  self = [super init]; // or initWithValue:0
  [self release];
  return nil;

如果没有这样的初始化器可以在没有有效数据的情况下工作,我想有人需要构建一些有效的伪数据。或者向其作者抱怨,直到那时只返回零并与泄漏一起生活:^)

2:ARC如何影响这种情况?

我的猜测:仍然以任何可能的方式完成初始化,然后返回零。你认为设置自我可能是多余的,但在某些情况下并非如此。在任何情况下,它都需要在那里使编译器警告静音。

  // can't proceed to call super's initWithValue: because we have no value
  // so do what? do this:
  self = [super init]; // finish init so ARC can release it having no strong references
  return nil;