2014-01-26 75 views
8

我們知道,與ARC我們需要一個__bridge一個ID轉換爲void *__bridge方法參數不需要?

void *t = (void *)self;   // ERROR: Cast of ... requires a bridged cast 
void *t = (__bridge void *)self; // CORRECT 

等都是C函數調用:

void f(void *t) { 
    .... 
} 

f((void *)self);   // ERROR 
f((__bridge void *)self); // CORRECT 

我想這應該保持的方法爲好,而事實上,這Beginning ARC in iOS 5 Tutorial給出了下面的例子,並說,__bridge需要:

MyClass *myObject = [[MyClass alloc] init]; 
[UIView beginAnimations:nil context:(__bridge void *)myObject]; 

然而,今天我不小心在我的一個程序中調用了方法調用中的__bridge,並且編譯並運行代碼時沒有任何問題。上述示例中的__bridge似乎是不必要的:

[UIView beginAnimations:nil context:(void *)myObject]; // COMPILED OK 

是這樣嗎?在這種情況下,__bridge真的不必要嗎?或者刪除它會改變代碼的含義?

回答

6

這是包括在ARC docs section 3.3.3(重點煤礦):

3.3.3 Conversion from retainable object pointer type in certain contexts

[beginning Apple 4.0, LLVM 3.1]

If an expression of retainable object pointer type is explicitly cast to a C retainable pointer type, the program is ill-formed as discussed above unless the result is immediately used:

  • to initialize a parameter in an Objective-C message send where the parameter is not marked with the cf_consumed attribute, or to
  • initialize a parameter in a direct call to an audited function where the parameter is not marked with the cf_consumed attribute.

在你的代碼,myObject是一個「可保留的對象指針」。 「C可保留指針類型」包括void*(這是一個稍微馬虎的定義,它們用作佔位符,因爲Core Foundation「對象」通常是void*)。

因此,如果用作方法參數,ObjC對象可以隱式轉換爲void*。在這種情況下,沒有額外的內存管理語義(即它等同於一個__bridge強制轉換)。 Section 7.8警告我們,void*未來可能不會這樣處理,但我不擔心這一點。如果發生這種情況,添加__bridge將是微不足道的。

有一點要記住的是myObject這裏沒有保護。在完成動畫之前,確保它以其他方式進行保留取決於您,否則您可能會崩潰。

+0

非常有趣,很好的發現。 +1,因爲你給了我又一個憎恨ARC的理由;-) – 2014-01-26 20:48:50

2

__bridge用於傳遞變量/引用(如保留計數)的所有權,這是對API的Objective-C或Objective-C的C API。

轉到通過Clang's doc

Bridged casts

A bridged cast is a C-style cast annotated with one of three keywords:

(__bridge T) op casts the operand to the destination type T. If T is a retainable object pointer type, then op must have a 

non-retainable pointer type. If T is a non-retainable pointer type, then op must have a retainable object pointer type. Otherwise the cast is ill-formed. There is no transfer of ownership, and ARC inserts no retain operations. (__bridge_retained T) op casts the operand, which must have retainable object pointer type, to the destination type, which must be a non-retainable pointer type. ARC retains the value, subject to the usual optimizations on local values, and the recipient is responsible for balancing that +1. (__bridge_transfer T) op casts the operand, which must have non-retainable pointer type, to the destination type, which must be a retainable object pointer type. ARC will release the value at the end of the enclosing full-expression, subject to the usual optimizations on local values.

These casts are required in order to transfer objects in and out of ARC control; see the rationale in the section on conversion of retainable object pointers.

Using a __bridge_retained or __bridge_transfer cast purely to convince ARC to emit an unbalanced retain or release, respectively, is poor form.

現在,

無效* T =(無效*)自我; //錯誤:Cast of ...需要橋接轉換 爲什麼它是錯誤的,因爲您嘗試將參考從Objective-C轉換爲C.它未能通過引用的所有權。

void * t =(__bridge void *)self; //更正 爲什麼它是正確的,因爲將您的客觀C參考轉移到C.根據LLVM的文檔。見上面給出的鑄造規則。

MyClass *myObject = [[MyClass alloc] init]; 
[UIView beginAnimations:nil context:(__bridge void *)myObject]; 

上面的紋路都是完全還行,因爲你通過C基準類型的上下文,而不是NULL

相關問題