C指針和OC對象之間如何轉(zhuǎn)換-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)C指針和OC對象之間如何轉(zhuǎn)換,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

10年積累的成都網(wǎng)站制作、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有屯溪免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

Core Foundation 框架

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

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

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

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

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

ARC 橋接

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

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

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

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

結(jié)合 ARC 和 內(nèi)存管理, 下面分別介紹一下.

Core Foundation 對象必須使用 CFRetain 和 CFRelease 來進(jìn)行內(nèi)存管理.

當(dāng)使用 Objective-C 和 Core Foundation 對象相互轉(zhuǎn)換的時(shí)候,必須讓編譯器知道,到底由誰來負(fù)責(zé)釋放對象,是否交給 ARC 處理, 只有正確的處理,才能避免內(nèi)存泄漏和 double free 導(dǎo)致程序崩潰.

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

__bridge_retained 等同于CFBridgingRetain().

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

示例:

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

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

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

關(guān)于 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 對象轉(zhuǎn)換為 OC 對象,同時(shí)將對象的管理權(quán)交給 ARC,開發(fā)者無需手動管理內(nèi)存.

示例:

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

CFBridgingRelease 實(shí)現(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 不改變對象所有權(quán), 需要我們自己來管理內(nèi)存, 它也是我們經(jīng)常使用的方法, 從某種程度上來說, 它是上面兩個(gè)方法的簡化版本.

__bridge 可以將 OC 對象 與 C 指針相互轉(zhuǎn)換, 示例:

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

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

C指針和OC對象之間如何轉(zhuǎn)換

再來另外一個(gè)例子, 如下:

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

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

野指針

運(yùn)行下面的示例:

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

會直接 crash, 如圖:

C指針和OC對象之間如何轉(zhuǎn)換

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

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

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

可以正常的運(yùn)行. 還可以修改為另一種方式:

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);

關(guān)于“C指針和OC對象之間如何轉(zhuǎn)換”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站muchs.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享文章:C指針和OC對象之間如何轉(zhuǎn)換-創(chuàng)新互聯(lián)
網(wǎng)站路徑:http://muchs.cn/article6/dgcsig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、App開發(fā)靜態(tài)網(wǎng)站、網(wǎng)站導(dǎo)航企業(yè)建站、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)