理解__bridge

比較受用, 全文轉載, 原文點此

為什么使用要使用 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 對象指針的相互轉換介紹,希望能幫助更多的小伙伴理解。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 轉至元數(shù)據(jù)結尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • 1.1 什么是自動引用計數(shù) 概念:在 LLVM 編譯器中設置 ARC(Automaitc Reference Co...
    __silhouette閱讀 5,472評論 1 17
  • 1,NSObject中description屬性的意義,它可以重寫嗎?答案:每當 NSLog(@"")函數(shù)中出現(xiàn) ...
    eightzg閱讀 4,340評論 2 19
  • 前言 從我開始學習iOS的時候,身邊的朋友、網(wǎng)上的博客都告訴我iOS的內(nèi)存管理是依靠引用計數(shù)的,然后說引用計數(shù)大于...
    蓋世英雄_ix4n04閱讀 663評論 0 1
  • 喜歡就關注我唄! 1.設計模式是什么? 你知道哪些設計模式,并簡要敘述? 設計模式是一種編碼經(jīng)驗,就是用比較成熟的...
    iOS白水閱讀 1,174評論 0 2

友情鏈接更多精彩內(nèi)容