最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C 指針和OC 對象之間的轉換方法

 更新時間:2018年03月08日 11:10:09   作者:veryitman  
這篇文章主要給大家介紹了關于C 指針和OC 對象之間的轉換方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

Core Foundation 框架

Core Foundation 框架 (CoreFoundation.framework) 是一組 C 語言接口, 簡稱 CF.

它們?yōu)?iOS 應用程序提供基本數(shù)據(jù)管理和服務功能.

如 Core Graphics、Core Text,并且我們可能需要將 CF 對象和OC 對象進行相互轉化,ARC 下,編譯器不會自動管理 CF 對象的內存,我們需要手動管理.

創(chuàng)建一個 CF 對象使用后, 需要使用 CFRelease 將其手動釋放, 換句話說, Core Foundation 對象類型不在 ARC 管理范疇內.

如何將 CF 和 OC 對象有效的結合起來, 在 ARC 環(huán)境下, 提供了 橋接 的技術, 即 ARC 下 OC 對象和 Core Foundation 對象之間的橋梁.

ARC 橋接

ARC 下 C 指針與 OC 指針(對象)之間轉換, 一般會用到下面的方法.

__bridge_retained <#CF type#>)<#expression#>
__bridge_transfer <#Objective-C type#>)<#expression#>
__bridge <#type#>)<#expression#>

也就是所謂的 橋接, 它是 Object-C 在 ARC 環(huán)境下開發(fā)出來的一種用作轉換 C 指針跟 OC (類)指針的一種轉換技術, 所以是 ARC 下的稱謂, 在 MRC 下沒有 橋接.

針對內存管理問題,ARC 可以管理 Objective-C 對象, 但不支持 Core Foundation 對象的管理,所以轉換后要注意一個問題:誰來釋放使用后的對象.

結合 ARC 和 內存管理, 下面分別介紹一下.

Core Foundation 對象必須使用 CFRetain 和 CFRelease 來進行內存管理.

當使用 Objective-C 和 Core Foundation 對象相互轉換的時候,必須讓編譯器知道,到底由誰來負責釋放對象,是否交給 ARC 處理, 只有正確的處理,才能避免內存泄漏和 double free 導致程序崩潰.

__bridge_retained <#CF type#>)<#expression#>

__bridge_retained 等同于 CFBridgingRetain() .

將 Objective-C 對象轉換為 Core Foundation 對象,把對象所有權橋接給 Core Foundation 對象,同時剝奪 ARC 的管理權,后續(xù)需要開發(fā)者使用 CFRelease 或者相關方法手動來釋放 CF 對象.

示例:

void *cPointer;
NSObject *objc = [[NSObject alloc] init];
//將 OC 對象轉換為 C 指針
cPointer = (__bridge_retained void*)objc;
//use cPointer ...
//需要釋放資源
CFRelease(cPointer);

在 ARC 下, CFBridgingRetain 實現(xiàn)如下:

NS_INLINE CF_RETURNS_RETAINED CFTypeRef _Nullable CFBridgingRetain(id _Nullable X) {
 return (__bridge_retained CFTypeRef)X;
}

關于 CFTypeRef, 如下:

typedef const CF_BRIDGED_TYPE(id) void * CFTypeRef;

所以 CFBridgingRetain 返回值是 const void * 類型的.

上面的示例可以改寫為:

const void *cPointer;
const NSObject *objc = [[NSObject alloc] init];
cPointer = CFBridgingRetain(objc);
 
//use cPointer ...
 
CFRelease(cPointer);

__bridge_transfer <#Objective-C type#>)<#expression#>

__bridge_transfer 等同于 CFBridgingRelease() .

將非 OC 對象轉換為 OC 對象,同時將對象的管理權交給 ARC,開發(fā)者無需手動管理內存.

示例:

CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef strUUID = CFUUIDCreateString(kCFAllocatorDefault, uuid);
NSString *str = (__bridge_transfer NSString *)strUUID;
//無需釋放 strUUID
//CFRelease(strUUID);
CFRelease(uuid);

CFBridgingRelease 實現(xiàn)如下:

NS_INLINE id _Nullable CFBridgingRelease(CFTypeRef CF_CONSUMED _Nullable X) {
 return (__bridge_transfer id)X;
}

上面的示例可以改寫為:

CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef strUUID = CFUUIDCreateString(kCFAllocatorDefault, uuid);
NSString *str = CFBridgingRelease(strUUID);
 
//無需釋放 strUUID
//CFRelease(strUUID);
 
CFRelease(uuid);

__bridge

__bridge 不改變對象所有權, 需要我們自己來管理內存, 它也是我們經(jīng)常使用的方法, 從某種程度上來說, 它是上面兩個方法的簡化版本.

__bridge 可以將 OC 對象 與 C 指針相互轉換, 示例:

//CFString -> OC 對象
CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "very", kCFStringEncodingUTF8);
NSString *nsString = (__bridge NSString *)cfString;
NSLog(@"CFString -> NSString: %@", nsString);
CFRelease(cfString);

如果將 CFRelease(cfString) 注釋掉, Xcode 的靜態(tài)檢測器會告訴你有內存泄露的情況, 如圖:

再來另外一個例子, 如下:

//OC 對象 -> CFString
NSString *nstr = @"itman";
CFStringRef cfStringRef = (__bridge CFStringRef)nstr;
NSLog(@"NSString -> CFString: %@", cfStringRef);
CFRelease(cfStringRef);

無論是使用 CFRelease(cfStringRef) , 還是注釋掉, 靜態(tài)檢測器都不會報錯. 說明這種情況下, 當前的內存管理已經(jīng)被 OC 對象管理.

野指針

運行下面的示例:

void *p;
{
 NSObject *objc = [[NSObject alloc] init];
 p = (__bridge void*)objc;
}
NSLog(@"mark: %@", (__bridge NSObject*)p);

會直接 crash, 如圖:

當 objc 這個對象超出作用域范圍,其內存就會被回收,接著在作用域范圍外用 void *p 去訪問 objc 的內存,就造成了野指針.

結合上面所說的, 我們可以讓指針 p 對 objc 進行引用即 retain 操作, 修改如下:

void *p;
{
 NSObject *objc = [[NSObject alloc] init];
 //p = (__bridge void*)objc;
 p = (__bridge_retained void*)objc;
}
NSLog(@"mark: %@", (__bridge NSObject*)p); 
// 一定要釋放
CFRelease(p);

可以正常的運行. 還可以修改為另一種方式:

void *p;
{
 NSObject *objc = [[NSObject alloc] init];
 //p = (__bridge void*)objc;
 //p = (__bridge_retained void*)objc;
 p = (void *)CFBridgingRetain(objc);
}
NSLog(@"mark: %@", (__bridge NSObject*)p);
// 一定要釋放
CFRelease(p);

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • C語言之復雜鏈表的復制詳解

    C語言之復雜鏈表的復制詳解

    這篇文章主要為大家詳細介紹了C語言之復雜鏈表的復制,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • C語言大小端模式、判斷大小端、大小端轉換方法詳解

    C語言大小端模式、判斷大小端、大小端轉換方法詳解

    這篇文章主要介紹了C語言大小端模式、判斷大小端、大小端轉換的相關資料,大端和小端是數(shù)據(jù)在內存中的存儲方式,大端模式下高字節(jié)存于低地址,小端模式則相反,大小端問題由數(shù)據(jù)類型多字節(jié)存儲引起,不同選擇形成不同存儲模式,需要的朋友可以參考下
    2024-10-10
  • C++智能指針詳解

    C++智能指針詳解

    從比較簡單的層面來看,智能指針是RAII(Resource Acquisition Is Initialization,資源獲取即初始化)機制對普通指針進行的一層封裝。這樣使得智能指針的行為動作像一個指針,本質上卻是一個對象,這樣可以方便管理一個對象的生命周期
    2022-08-08
  • C++使用jsoncpp庫解析Json

    C++使用jsoncpp庫解析Json

    對json的解析操作是我們日常開發(fā)中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關于C++使用jsoncpp庫解析Json的相關資料,需要的朋友可以參考下
    2021-06-06
  • C++中利用cout和fstream采用非科學計數(shù)法輸出

    C++中利用cout和fstream采用非科學計數(shù)法輸出

    這篇文章主要介紹了C++中利用cout和fstream采用非科學計數(shù)法輸出方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Qt增加版本公司等信息兩種方式

    Qt增加版本公司等信息兩種方式

    在項目中生成exe或者動態(tài)庫過程中可能需要加入公司信息、版本號、說明等等,下面這篇文章主要給大家介紹了關于Qt增加版本公司等信息的兩種方式,需要的朋友可以參考下
    2024-01-01
  • 基于WTL 雙緩沖(double buffer)繪圖的分析詳解

    基于WTL 雙緩沖(double buffer)繪圖的分析詳解

    本篇文章是對WTL下使用雙緩沖(double buffer)繪圖進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言編程之三個方法實現(xiàn)strlen函數(shù)

    C語言編程之三個方法實現(xiàn)strlen函數(shù)

    本篇文章是C語言編程篇,主要為大家介紹C語言編程中實現(xiàn)strlen函數(shù)的三個方法講解,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09
  • 詳解C語言數(shù)組靈活多變的訪問形式

    詳解C語言數(shù)組靈活多變的訪問形式

    這篇文章主要介紹了詳解C語言數(shù)組靈活多變的訪問形式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • javascript 兩種聲明函數(shù)的方式的分析

    javascript 兩種聲明函數(shù)的方式的分析

    這篇文章主要介紹了javascript 兩種聲明函數(shù)的方式的分析的相關資料,需要的朋友可以參考下
    2017-02-02

最新評論

图木舒克市| 黔西| 丹凤县| 东丰县| 徐州市| 永清县| 南城县| 临泉县| 台前县| 怀来县| 雷山县| 深州市| 禹州市| 深圳市| 怀远县| 始兴县| 绍兴市| 应用必备| 奎屯市| 焦作市| 天等县| 沂源县| 尼木县| 芮城县| 定西市| 尼玛县| 武穴市| 山阴县| 长子县| 新邵县| 新营市| 托克逊县| 长阳| 河曲县| 宝兴县| 黄陵县| 台中县| 安国市| 卫辉市| 临洮县| 广河县|