从 [[class alloc] init] 返回 nil 被认为是好的做法吗?

发布于 2024-09-14 06:27:49 字数 171 浏览 8 评论 0原文

这是 Objective-C 中的常见习惯用法吗?

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

And is it a common idiom in Objective-C.

I've only seen this used on [[NSImage alloc] initWithContentsOfFile: str] and it always make me think there is a memory leak, because i called alloc and the mantra is:
"Call alloc and you must call release" - unless its one of the cases where you don't need to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山有枢 2024-09-21 06:27:49

这是一个常见的习惯用法,表示初始化对象时出现错误。你是对的,但是,分配的实例必须被释放。所以模式是

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

  return self;
}

It is a common idiom to indicate a error in initializing the object. You are correct, however, the allocated instance must be released. So the pattern would be

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

  return self;
}
〃温暖了心ぐ 2024-09-21 06:27:49

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

也接受参数的 init 方法(例如: initWithXxx:(Xxx*)x 例如 NSStringinitWithBytes:)可以返回nil 无需调用 [super init] 。 init 方法必须像任何方法一样管理内存。只是 init 有一些不寻常的行为,即根据它的选择返回其自身或返回某个其他对象。一般来说,没有太多要求。

See using alloc and init for more issues and answers regarding init methods.

An init method that also accepts args (ex: initWithXxx:(Xxx*)x such as NSString's initWithBytes:) could return nil without ever calling [super init] if (for example) it did not like an arg it received. An init method must manage memory just like any method. It's just that init has the somewhat unusual behavior of returning its self or returning some other object, as it chooses. Not much call for that in general.

少年亿悲伤 2024-09-21 06:27:49

我还没有看到该主题的明确答案的两个后续问题 - 现在在其自己的问题中重复,从 [[class alloc] init] 返回 nil 的后续操作

1:如何处理在调用 super 之前未满足某些先决条件的 init。例如,假设在此 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。如有必要,请调用 bare init 或任何其他可以在释放 self 之前完成将 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;

如果没有这样的初始化程序可以在没有有效数据的情况下工作,我想人们需要构造一些有效的虚拟数据。或者向其作者投诉,在此之前只需返回 nil 并接受泄漏:^)

2:ARC 对情况有何影响?

我的猜测:仍然以任何可能的方式完成 init,然后返回 nil。您可能认为设置 self 可能是多余的,但在某些情况下并非如此。无论如何,它必须存在以消除编译器警告。

  // 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;

Two follow-up questions to this topic that I haven't seen definitive answers to - now repeated in its own question, Followup to returning nil from a [[class alloc] init]

1: What to do with an init that fails some preconditions before it can call super. Example, suppose in this initWithStuff: method being passed nil or in general having no value to pass to initWithValue: is an absolute failure and we definitely want to return 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];
}

Perhaps a clearer example is if the designated initializer method we wrap takes an object pointer and throws an exception if its passed nil. We definitely need to short-circuit that init call that would cause an exception.

My guess: init by any means possible, and only then release self before returning nil. If necessary, call bare init or any other initializer that will work to finish putting self into a known state before releasing it.

  // 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;

And if there were no such initializer that will work without valid data, I guess one would need to construct some valid, dummy data. Or complain to its author and until then just return nil and live with the leak :^)

2: How does ARC affect the situation?

My guess: still finish init by any means possible, then just return nil. You'd think setting self might be redundant, but in some cases it's not. In any case, it but it needs to be there to silence a compiler warning.

  // 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文