【问题标题】:Is the following iOS code safe? (__autoreleasing semantics)下面的 iOS 代码安全吗? (__autoreleasing 语义)
【发布时间】:2013-03-18 21:16:09
【问题描述】:
-(NSData *)jsonRepresentation:(NSError **error)error {
   NSDictionary *dict = [self getDictRepresentation];
   return [NSJSONSerialization dataWithJSONObject:dict options:nil error:error];
}

// Some other place...

NSError *__autoreleasing error = nil;
NSData *json = [obj jsonRepresentation:&error];

自动释放语义是否安全地将error 向上传递到我的第二个代码块?

【问题讨论】:

  • 这些自动释放机制实际上是为局部变量隐含的(除了少数例外),不需要明确说明。但是,是的,它是正确的。
  • @RichardJ.RossIII:你什么意思? obj-c 类型的局部变量默认为__strong,除非另有说明。
  • @KevinBallard 我的意思是,只要它们可以延长声明它们的块的生命周期,它们的行为就像一个自动释放值。特别是返回值变成 __autoreleasing(当然,除非您指定另一个返回类型属性)。在极少数情况下真正需要 __autoreleasing。
  • @RichardJ.RossIII:我不确定你想说什么。方法的返回值根本不是所有权限定的。相反,它们被认为是“保留的返回值”或“未保留的返回值”,在后一种情况下,ARC 只保证对象将在调用边界上存活。这可能涉及将其放入自动释放池中,也可能不。

标签: ios automatic-ref-counting autorelease


【解决方案1】:

根据the clang ARC specNSError ** 形式的方法参数(或者更确切地说,指向任何 obj-c 对象的指针)被隐式假定为NSError * __autoreleasing *。这意味着错误将在方法中自动释放。

至于调用站点,如果您使用 __autoreleasing 变量调用它,就像您所做的那样,那么一切都很好。事实上,我推荐这种模式。但是,如果您使用 __strong 变量调用它,它仍然可以工作。在这种情况下,编译器将生成一个未命名的__autoreleasing 临时地址,将其地址传递给方法,然后在返回时,将临时地址分配给__strong。所以如果你有

NSError *foo;
[bar callMethodWithError:&foo];

编译器会将其视为

NSError *foo;
NSError * __autoreleasing tmp = foo;
[bar callMethodWithError:&tmp];
foo = tmp;

It's actually slightly more complicated than that 如果输出参数被标记为out,但这通常是它的工作原理。

【讨论】:

    【解决方案2】:

    是的,它是正确的,但是你应该在方法声明中指定这个修饰符,而不是在变量的声明中。甚至 Apple 的官方文档也明确提到了这种情况:

    __autoreleasing 用于表示通过引用 (id *) 传递并在返回时自动释放的参数。

    【讨论】:

    • 请注意,您应该在方法声明本身上指定__autoreleasing,而不是方法的参数。
    • @RichardJ.RossIII 谢谢,也添加了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 2014-02-16
    相关资源
    最近更新 更多