2012-03-25 64 views
32

我很困惑bridgebridge_transfer,这是正确的吗?iOS桥vs bridge_transfer

-(void)getData{ 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 
    NSArray *allPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook); 

    NSString *name; 
    for (int i = 0; i < [allPeople count]; i++) 
    { 
     name = (__bridge_transfer NSString *) ABRecordCopyValue((__bridge ABRecordRef)[allPeople objectAtIndex:i], kABPersonFirstNameProperty); 
    } 
    CFRelease(addressBook); 
    allPeople = nil; 
} 

有没有人能解释我如何使用它们?

回答

41

如果您启用了自动引用计数(ARC),则代码是正确的。

您的报表中有两个__bridge_transfer。因此,创建的CFObjects的所有权将被转移到NSObjects。如果您打开了ARC,它们将自动释放。如果您使用__bridge代替这两个语句,则需要明确呼叫CFRelease以释放由*Copy API创建的CFObjects。

__bridge声明也是正确的。因为你在CF API中引用了一个NSObject。您没有转让所有权,所以ARC会将其释放。

+0

thx,你能解释一下什么是“转让所有权”? – Rinat 2012-03-25 11:10:16

+8

所有权是内存管理中一个重要的关键概念。对象的“所有者”负责释放其内存。如果它没有做到这一点,对象将会泄漏。一个对象可以有多个所有者,所以在这种情况下,超出范围的最后一个所有者负责解除分配。 ARC会自动执行此操作,但仅适用于Objective-C对象。 CoreFoundation对象是香草C对象,所以你需要给编译器提示如何处理它们。如果您将“所有权”转让给ARC,那么您认为ARC有责任解除分配该对象。 – borrrden 2012-03-25 11:25:06

+2

抱歉,迟到的回应。所有权主要是由谁来负责释放对象。如果您想了解详细信息,请参阅[所有权政策](https://developer.apple.com/library/mac/#documentation/CoreFOundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html)。 – 2012-03-25 14:59:32

19

这非常非常简单,当你使用ARC(自动引用计数)时,编译器会负责计算你的变量指向了多少个对象。当计数到0时,对象会自动分配。对于来自低级结构的东西,比如核心基础,编译器不知道该怎么做。所以,如果你只是想告诉编译器“忽略这一个,我会在需要时释放它”,所以你使用BRIDGE。或Bridge传输,如果你想说“把它作为一个对象并在参考变为0时释放它”)。

当你这样做时,你创建一个副本,在正常情况下应该由“CFRelease” :

ABAddressBookCopyArrayOfAllPeople(addressBook) 

但是加入这个,你是转移的所有权转让给一个Objective-C的对象:

NSArray *allPeople = (__bridge_transfer NSArray*)........ 

所以NSArray的将ARC管理


注意,如JRG提到,这样做:

CFRelease(addressBook); 

在不影响反正新创建的对象,而是原来你还是要手动释放:(这很容易告诉因为这些方法通常有创建复制他们的名字关键字)


的东西,不发生在你的代码中,但你应该小心的是释放CFRelease的NULL核心基础对象将导致错误。正如保罗在评论中提到的那样。

+2

不像'[nil release]'很好,'CFRelease(NULL)'会导致错误。 – paulmelnikow 2013-01-30 16:12:53

+1

是的,你是对的,http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFTypeRef/Reference/reference.html“如果cf是NULL,这将导致运行时错误,你的应用程序将崩溃“。 – Pochi 2013-01-30 16:42:03

+0

-1:'NSArray * allPeople =(__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);'传输返回数组的所有权。这与'addressBook'没有任何关系。相反,'addressBook'必须被释放,因为它是使用“create”方法('ABAddressBookCreate')创建的。否则,它会泄漏。 – 2015-12-02 02:14:28

0

一个编辑:我相信一个零对象上调用CFRelease确实会导致应用崩溃

1

路易斯奥斯卡我还在我的ARC的理解,但我相信通讯录确实需要CFRelease。 ARC不管理地址簿。 NSArray * allPeople由ARC通过__bridge_transfer投影提示进行管理,并将其作为原始副本创建。没有CFRelease,addressBook将会泄漏。