下面的 iOS 代码安全吗? (__autoreleasing 语义)
Posted
技术标签:
【中文标题】下面的 iOS 代码安全吗? (__autoreleasing 语义)【英文标题】:Is the following iOS code safe? (__autoreleasing semantics) 【发布时间】: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 只保证对象将在调用边界上存活。这可能涉及将其放入自动释放池中,也可能不。
【参考方案1】:
根据the clang ARC spec,NSError **
形式的方法参数(或者更确切地说,指向任何 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 谢谢,也添加了。以上是关于下面的 iOS 代码安全吗? (__autoreleasing 语义)的主要内容,如果未能解决你的问题,请参考以下文章