我正在使用ARC,并且在使用__bridge_transfer时有混淆。我有一个属性userName如下:
@property (nonatomic, retain) NSString *userName;
...
@synthesize userName = _userName;
...病例1
NSString *name = (__bridge_transfer NSString *)ABRecordCopyCompositeName(person);
self.userName = name;案例2
self.userName = (__bridge_transfer NSString *)ABRecordCopyCompositeName(person);其中person的类型为ABRecordRef。
在1的情况下,ARC会释放局部变量名(据我理解,如果我错了请纠正我),但是万一2会发生什么呢?我应该在__bridge中使用2还是CASE 2根本不应该使用?在2与__bridge_transfer或__bridge的情况下,如何平衡引用计数?
如果2与__bridge_transfer一起,__bridge_transfer会释放对象(对象作为参数传递给setter (void)setUserName:(NSString *)userName)吗?
发布于 2013-01-16 07:09:43
当您调用ABRecordCopyCompositeName()时,必须有人在某个时候释放返回的对象。使用__bridge_transfer确保ARC将为您释放该对象。如果没有__bridge_transfer,则必须手动释放返回的对象。这是唯一的两个选择。
因此,在这两种情况下都必须使用__bridge_transfer。
一个很好的练习是使用__bridge而不是__bridge_transfer来诱导泄漏,然后使用Xcode和to来尝试查找泄漏。编译器会发现漏洞吗?静态分析(项目->分析)是否发现漏洞?仪器能查到漏水吗?如果是这样,那么您将知道如何检查__bridge_transfer是否解决了这个问题。
发布于 2015-02-13 08:27:29
案例1和案例2是等价的。你可以这样想:
案例1:
-(void)func {
NSString *name = someObject; // Retain, so +1 on the reference count
self.userName = name; // Retain, so +1 on the reference count
// End of function, name is going out of scope,
// so release name, so -1 on the reference count.
// Total change to the reference count: +1 for self.userName.
}案例2:
-(void)func {
self.userName = someObject; // Retain, so +1 on the reference count
// End of function.
// Total change to the reference count: +1 for self.userName.
}所以他们的工作原理是一样的。请注意,如果这样做是安全的,编译器就可以取消保留和释放对。在这样一个简单的例子中,它肯定会使它们消失。考虑到它的所有+1和-1的变化,引用计数只是为了使它更清楚。
要回答关于__bridge和__bridge_transfer的问题:您已经调用了ABRecordCopyCompositeName,它返回对非托管对象( CFStringRef)的引用。函数名中的Copy告诉您,这个对象现在是您拥有的,您需要最终释放它。
您可以通过调用CFRelease来做到这一点,也可以要求ARC为您做这件事。__bridge告诉ARC,它不允许拥有(换句话说,您想手动释放对象,或者它不属于您)。__bridge_transfer告诉ARC,它应该获得所有权,并在完整表达式的末尾释放对象(换句话说,您要求ARC为您完成发布)。
用__bridge_transfer
self.userName = (__bridge_transfer NSString *)ABRecordCopyCompositeName(person); // +1 inside ABRecordCopyCompositeName, +1 for self.userName, -1 at the end, because of the __bridge_transfer.
// self.userName now is the only strong reference. Good.用__bridge
CFStringRef userName = ABRecordCopyCompositeName(person); // +1 inside ABRecordCopyCompositeName.
self.userName = (__bridge NSString *)userName; // +1 for self.userName, ARC does nothing because of the __bridge.
CFRelease(userName); // -1.
// self.userName now is the only strong reference. Good.使用__bridge和内存泄漏:
self.userName = (__bridge NSString *)ABRecordCopyCompositeName(person); // +1 inside ABRecordCopyCompositeName, +1 for self.userName, ARC does nothing because of the __bridge.
// self.userName now is one strong reference, but reference count is 2.
// Memory leak.发布于 2015-09-11 02:25:58
正因为这令人困惑,我建议您使用CFBridgingRelease()和CFBridgingRetain(),而不是分别对__bridge_transfer和__bridge_retained进行强制转换。然后,您需要记住的唯一“不寻常”的类型是__bridge,它对所有权没有任何作用。
我发现它更容易记住,因为像ABRecordCopyCompositeName()这样的东西留给您返回对象CFRelease()的责任,您可以使用CFBridgingRelease()来履行这个责任,这种类比是显而易见的。
类似地,如果对象指针已经是Core类型,则只在上下文中使用CFBridgingRetain()。
所以,您的代码可能是:
NSString *name = CFBridgingRelease(ABRecordCopyCompositeName(person));
self.userName = name;或者:
self.userName = CFBridgingRelease(ABRecordCopyCompositeName(person));在这两种情况下,CFBridgingRelease()在函数名中平衡了Copy,这意味着您有责任释放对象。在那之后,一切都是别人的责任。弧管理name变量。userName属性的setter的实现者对此进行管理。(在这种情况下,碰巧也是ARC,但这与此无关。)
https://stackoverflow.com/questions/14352494
复制相似问题