比較受用, 全文轉載, 原文點此
為什么使用要使用 Object-C++
在 iOS 開發(fā)當中,難免會使用到 OC 跟 C++混編的情況,一是為了程序?qū)ω撠熡嬎阈阅艿奶岣?,二是因為某些三方開源庫是用 C++ 來寫的,這兩個原因也是讓我下決心學好 C++ 的因素,畢竟開源才是王道,一直只寫著 OC 卻不能窺其究竟,確實難受,讓只能讓人停留在門外,坐井觀天。
什么是橋接 ?
橋接,是 object-c 在 ARC 環(huán)境下開發(fā)出來的一種用作轉換 C 指針跟 OC 類指針的一種轉換技術。
當然,這種技術在 MRC 中是不存在的,也就是橋接是 ARC 的連帶產(chǎn)物,因為 ARC 就是解放了我們程序員的雙手,當然對內(nèi)存的概念又淡化了,所以在 ARC 未被業(yè)界接受之前多少也是因為這個橋接讓人們感覺惡心。
橋接用到的3個方法:
(__bridge <#type#>)<#expression#>
(__bridge_retained <#CF type#>)<#expression#>
(__bridge_transfer <#Objective-C type#>)<#expression#>)
橋接方法的用途:
__bridge :用作于普通的 C 指針與 OC 指針的轉換,不做任何操作。
void *p;
NSObject *objc = [[NSObject alloc] init];
p = (__bridge void*)objc;
這里的 void *p 指針直接指向了 NSObject *objc 這個 OC 類,p 指針并不擁有 OC 對象,跟普通的指針指向地址無疑。所以這個出現(xiàn)了一個問題,OC 對象被釋放,p 指針也就 Gameover 了。
__bridge_retained:用作 C 指針與 OC 指針的轉換,并且也用擁有著被轉換對象的所有權
那么這個是什么意思呢?可以先看下面展示代碼
@interface ABSClass : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation ABSClass
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
void *p;
{
ABSClass *objc = [[ABSClass alloc]init];
objc.name = @"我們";
p = (__bridge void*)objc;
}
NSLog(@"%@", [(__bridge ABSClass *)p name]);
}
return 0;
}
這段代碼看上去大體與上面一段一樣,但是我們添加了一個作用域 {} , 在作用域中創(chuàng)建 ABSClass *objc 這個對象,然后用作用域外的 p,指針進行橋接(__bridge)指向,然后輸出 ABSClass objc這個對象的name屬性的值,按道理來說我們會看到控制臺上輸出我們這兩個字。 但是,當我們一運行程序,毫無疑問,程序很崩潰在NSLog(@”%@”, [(__bridge ABSClass )p name]);這句代碼中。 有點基礎的小伙伴都知道,當ABSClass objc這個對象出了作用域范圍,內(nèi)存就會被回收,但是我們在作用域范圍外還用void p去訪問objc 的內(nèi)存,當然會崩潰啦。
那么,我們嘗試修改為以下代碼
@interface ABSClass : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation ABSClass
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
void *p;
{
ABSClass *objc = [[ABSClass alloc]init];
objc.name = @"我們";
p = (__bridge_retained void*)objc;
}
NSLog(@"%@", [(__bridge ABSClass *)p name]);
}
return 0;
}
程序正常運行,因為我們使用了 __bridge_retained 就相當于 MRC 下的 retain ,將內(nèi)存計數(shù)器 +1,然后用 void *p 指向改內(nèi)存,所以當 *objc過了作用域,引用計算器 -1,也并沒有釋放 void *p 所引用的內(nèi)存。
__bridge_transfer:用作 C 指針與 OC 指針的轉換,并在擁有對象所有權后將原先對象所有權釋放。(只支持 C 指針轉換 OC 對象指針)
說起來相當繞口,其實可以理解為先將對象的引用計數(shù)器 +1,然后再將引用計數(shù)器 -1。
通過以下代碼展現(xiàn):
@interface ABSClass : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation ABSClass
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
void *p;
@autoreleasepool {
ABSClass *obj = [[ABSClass alloc] init];
obj.name = @"我們";
p = (__bridge_retained void *)obj;
}
id obj = (__bridge_transfer id)p;
NSLog(@"%@", [(__bridge ABSClass *)p name]);
NSLog(@"%@", [(ABSClass *)obj name]);
NSLog(@"Hello, World!");
}
return 0;
}
以上代碼可以正確運行,在我們將 void *p 指針轉換為進行 __bridge_transfer 為 OC 指針,這個操作其實相當于 - (void)set: 操作,轉換為 MRC 為如下代碼 :
id obj = (id)p
[obj retain];
[(id)p release];
我們先將新值 retain,然后再將舊值 release,這樣是為了保證引用計數(shù)器始終為1,一個 retain 對應一個 release。
好了,以上做法就是 C/C++ 指針與 OC 對象指針的相互轉換介紹,希望能幫助更多的小伙伴理解。