Iva*_*vic 5 objective-c automatic-ref-counting
我只是CABasicAnimation为shadowPath属性配置,这让我很好奇:
shadowAnimation.toValue = (id)newShadowPath.CGPath;
Run Code Online (Sandbox Code Playgroud)
[注意:shadowAnimation是一个CABasicAnimation对象,newShadowPath是一个UIBezierPath对象]
这是有效的,Xcode中没有错误/警告.但是,如果我这样写:
CGPathRef test = newShadowPath.CGPath;
shadowAnimation.toValue = (id)test;
Run Code Online (Sandbox Code Playgroud)
这将无法编译,抛出此警告消息:
Cast of C pointer type 'CGPathRef' (aka 'const struct CGPath *') to Objective-C pointer type 'id' requires a bridged cast
Run Code Online (Sandbox Code Playgroud)
所以它需要我输入它:
shadowAnimation.toValue = (__bridge id)test;
Run Code Online (Sandbox Code Playgroud)
现在为什么会这样呢?当我只使用(id)newShadowPath.CGPath时,为什么我在初始示例中没有得到相同的错误; ?__bridge不管Xcode没有检测到任何问题,将投射放在那里也是正确的吗?或者我错过了这里有什么区别?
造成差异的原因在于 clang 3.1 中引入的新的(并且有点复杂)转换规则。
首先,让我们把它归结为:
@@interface Foo : NSObject
+ (CGPathRef)bar;
@end
CGPathRef foo();
void test()
{
// works without bridged cast:
id a = (id)[Foo bar];
// needs bridged cast
id b = (__bridge id)foo();
}
Run Code Online (Sandbox Code Playgroud)
因此,在转换消息结果时,我们可以省略 brdge 转换,而普通函数调用需要它。这看起来很奇怪。
差异的原因在于 ARC 如何解释函数和方法名称以及如何导出有关所谓的C 可保留指针类型的保留计数的假设(Core Foundation 对象)的保留计数的假设。
在ARC 指南的第 3.3.2 节(“转换为具有已知语义的表达式的可保留对象指针类型”)中,您将找到差异的原因:
如果表达式是C 可保留指针类型的右值并且它是 [...] 消息发送 [...]
和
如果已知强制转换操作数未保留[...],则转换将被视为 __bridge 强制转换
同一部分描述了为什么这不适用于 C 函数,以及如何修饰它们以使 clang 做出类似的假设。因此,我们也可以修改上面的示例,以消除 C 函数调用的桥接转换:
CGPathRef foo() __attribute__((cf_returns_not_retained));
Run Code Online (Sandbox Code Playgroud)
回答你的最后一个问题:在两个地方使用桥模型都是安全的。它甚至确保 ARC 选择正确的__bridge转换(它可以__bridge_transfer根据方法的名称选择转换。__bridge但在本例中它将使用 )。
| 归档时间: |
|
| 查看次数: |
2047 次 |
| 最近记录: |