加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – 声明方法参数__autoreleasing有什么好处?

发布时间:2020-12-16 04:56:26 所属栏目:百科 来源:网络整理
导读:按照 Transitioning to ARC Release Notes: __autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return. 例如: – (BOOL)performOperationWithError:(NSError * __autoreleasing *)错误; 但与上
按照 Transitioning to ARC Release Notes:

__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.

例如:

– (BOOL)performOperationWithError:(NSError * __autoreleasing *)错误;

但与上述相比,上述优点有哪些:

– (BOOL)performOperationWithError:(NSError * __strong *)错误;

更新:

有几个答案引用temp var技巧编译器来处理var和argument之间的不匹配作为__autoreleasing的优点.我不明白为什么编译器不能为__strong参数做同样的技巧.我的意思是,对于__weak var和__strong参数,编译器可以类似地执行此操作:

NSError * __weak error;
NSError * __strong tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
    // Report the error.
}

编译器知道 – (BOOL)performOperationWithError:(NSError * __strong *)错误;返回一个强引用(1),因此它就像任何新的族方法一样处理它.由于tmp与错误存在于相同的范围内,因此编译器可以合理地使其保持活动,只要出现错误,因此__weak引用(错误)现在由__strong引用(tmp)支持,并且在范围结束之前不会无效.

解决方法

TL;博士

在这种情况下,将__weak对象隐式转换为__strong对象会改变程序的语义,这是编译器永远不应该做的事情.

场景

我们来举个例子吧

NSError *error;
BOOL success = [myObject performOperationWithError:&error];
if (!success) {
    // Report the error
}

在这种情况下,错误局部变量由ARC自动推断为__strong.

同时出现错误参数

-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;

属于NSError * __autoreleasing *类型.

请注意,在任何情况下,ARC都会将通过引用传递的参数(id *)推断为类型为id __autoreleasing *,因此上述签名相当于

-(BOOL)performOperationWithError:(NSError **)error;

在ARC下.

因此我们将不匹配,因为我们将__strong带注释的变量传递给期望__autoreleasing参数的方法.

在引擎盖下

在我们的示例中,编译器将通过创建本地__autoreleasing tmp变量来解决此类不匹配问题.

代码变成了

NSError * __strong error;
NSError * __autoreleasing tmp = error;
BOOL success = [myObject performOperationWithError:&tmp];
error = tmp;
if (!success) {
    // Report the error.
}

替代

我们现在假装我们可以更改performOperationWithError的签名:

如果我们想避免使用tmp变量的“编译器技巧”,我们可以将我们的签名声明为

-(BOOL)performOperationWithError:(NSError * __strong *)error;

我们有一个__strong变量,我们现在将它传递给一个期望__strong参数的方法,所以我们只是消除了不匹配.

看起来不错,为什么不总是声明__strong参数?

一个原因是将参数声明为__autoreleasing将使该方法甚至接受__weak引用.

在当前的例子中它没有多大意义,但是在某些情况下我们希望通过引用传递一个__weak变量并声明__autoreleasing(或让ARC推断它)将允许我们这样做.

ARC将应用上面看到的相同技巧,创建一个__autoreleasing tmp变量.

结论

到目前为止提出的机制是以pass-by-writeback的名义进行的.

这种机制设计用于__autoreleasing,__strong和__weak变量,这样程序员可以安全地依赖编译器进行的类型推断,而不必过多关注注释变量.

在某些情况下声明id __strong *参数可能有意义,但通常它可能会导致编译器生成意外错误.

我的建议是:“让编译器发挥他的魔力,你会很好”

更新

I don’t see why compiler can not do the same trick for __strong argument.

告诉编译器以__autoreleasing方式处理__strong或__weak变量的管理它没关系,因为它基本上意味着:“请,编译器,自动做正确的事情”.

这就是为什么上面看到的技巧可以毫无问题地运作.

另一方面,如果你将一个变量声明为__weak,你可能有充分的理由这么做,而你想要的最后一件事就是在你明确指出的时候隐含地保留它.这将从根本上改变你所编写的代码片段的语义,因此编译器不会这样做(感谢上帝!).

换一种说法

__weak – > __autoreleasing好__strong – > __autoreleasing好__weak< - > __strong错了!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读