【问题标题】:What's the right way to set an NSError outparam from inside an autoreleasepool block?从 autoreleasepool 块中设置 NSError outparam 的正确方法是什么?
【发布时间】:2013-01-07 12:54:10
【问题描述】:

我有这样的方法:

- (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error
{
    @autoreleasepool {

          // Start processing.

          // Find some partway through error..
          if (error) {
              *error = [NSError errorWithDomain...];
              return NO;
          }

          // More processing.
    }
}

这被破坏和崩溃了,因为 NSError 是自动释放的,当返回发生时,池被耗尽,所以调用者得到的东西现在是假的。

我知道我可以对方法进行重大重新设计,因此我会收集 autorelease 块之外的所有错误案例,但我想了解在这种情况下是否有处理错误对象的正确方法。我不能在池块之​​外分配/初始化推测性 NSError,因为域和代码属性是只读的(我仍然认为当方法返回时引用会消失)。

如果我把方法声明改成这样,问题就解决了:

- (void)processAThing:(id)thing error:(NSError * __strong *)error

但是我需要以一种非标准的方式在调用站点上大惊小怪,这似乎让调用者为我的内部自动释放池付出代价。

有什么想法吗?谢谢。

【问题讨论】:

  • 将签名更改为 (NSError * __strong *)error 实际上对我来说似乎是一个合理的选择。

标签: ios objective-c automatic-ref-counting autorelease


【解决方案1】:

我自己也遇到过这个问题。在这种情况下,我认为您只需要在 @autoreleasepool 之前声明一个新的强引用,并在该临时引用的 @autoreleasepool 块之后设置方法参数。

- (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error {
  __strong NSError *errOut = nil;
  @autoreleasepool {
    // do your stuff and set errOut instead of error
  }
  if (error) {
    *error = errOut;
  }
}

(在浏览器中输入,编译器未检查错误)

至于你的过早返回,我猜你必须使用跳转标签(即使它不漂亮)。

【讨论】:

  • 你不需要写__strong。默认情况下是这样的
  • 是的,我把它放在那里只是为了澄清。
  • 谢谢埃里克。听起来没有其他明显的模式可以使用,除了最小化 autorelease 块的范围并将 outparam 设置在它之外。
  • 顺便说一句,如果您需要多次返回(例如由于多个错误原因),您可以将整个自动释放池包装在 @try 块中,然后在 @ 中执行 *error = errOut 舞蹈987654326@ 块(@catch 是可选的)。这将确保在任何情况下返回之前正确分配输出错误(感谢我的同事 Stephan 提出这个问题)。
猜你喜欢
  • 2019-04-09
  • 2011-08-22
  • 2017-12-17
  • 1970-01-01
  • 2021-12-06
  • 2022-11-08
  • 2013-12-26
  • 2014-03-16
  • 1970-01-01
相关资源
最近更新 更多