iOS引用轉換:Foundation與Core Foundation對
1. 兩個框架的基本知識
1.1 Foundation
框架名是Foundation.framework
,在Xcode新建工程時可以選擇匯入(其實會預設自動依賴好)。Foundation框架允許使用一些基本物件,如數字和字串,以及一些物件集合,如陣列,字典和集合,其他功能包括處理日期和時間、記憶體管理、處理檔案系統、儲存(或歸檔)物件、處理幾何資料結構(如點和長方形)。這個框架中的類都是一些最基礎的類。來自於這個框架的類名以NS
開頭。
Foundation框架提供了非常多好用的類, 比如:
NSString : 字串 NSArray : 陣列 NSDictionary : 字典 NSDate : 日期 NSData : 資料 NSNumber : 數字
1.2 Core Foundation
Core Foundation 物件主要使用在用C語言編寫的Core Foundation 框架中,並使用引用計數的物件。在ARC無效時,Core Foundation 框架中的retain/release 分別是 CFRetain /CFRelease。
框架CoreFoundation.framework
是一組C語言介面,它們為iOS應用程式提供基本資料管理和服務功能。下面列舉該框架支援進行管理的資料以及可提供的服務。查閱Core Foundation的完整API 。
CF的引用定義:
CFStringRef
與CFArrayRef
查閱CFArrayRef 的定義
查閱CFStringRef 的定義
typedef const struct __CFString * CFStringRef;typedef const struct __CFArray * CFArrayRef;
CF的原始碼:
__CFString
與__CFArray
查閱CF中結構體的原始碼 。
這些結構體的定義如下:
struct __CFArray { CFRuntimeBase _base; CFIndex _count; /* number of objects */ CFIndex _mutations; int32_t _mutInProgress; __strong void *_store; /* can be NULL when MutableDeque */};
struct __CFString { CFRuntimeBase base; union { // In many cases the allocated structs are smaller than these struct __inline1 { CFIndex length; } inline1; // Bytes follow the length struct __notInlineImmutable1 { void *buffer; // Note that the buffer is in the same place for all non-inline variants of CFString CFIndex length; CFAllocatorRef contentsDeallocator; // Optional; just the dealloc func is used } notInlineImmutable1; // This is the usual not-inline immutable CFString struct __notInlineImmutable2 { void *buffer; CFAllocatorRef contentsDeallocator; // Optional; just the dealloc func is used } notInlineImmutable2; // This is the not-inline immutable CFString when length is stored with the contents (first byte) struct __notInlineMutable notInlineMutable; } variants; };
1.3 兩者關係
Core Foundation 框架和 Foundation 框架緊密相關,它們為相同功能提供介面,但 Foundation 框架提供Objective-C介面。如果您將Foundation 物件和 Core Foundation 型別摻雜使用,則可利用兩個框架之間的 “toll-free bridging”。所謂的Toll-free bridging是說您可以在某個框架的方法或函式同時使用 Core Foundation 和 Foundation 框架中的某些型別。
很多資料型別支援這一特性,其中包括群體和字串資料型別。每個框架的類和型別描述都會對某個物件是否為 ,應和什麼物件橋接進行說明。如需進一步資訊,請閱讀 。
2. Objective-C指標與CoreFoundation指標之間的轉換
2.1 MRC下的轉換
CF-->OC
強制轉換符:(CFStringRef)
OC-->CF
強制轉換符:(NSString *)
例子
-(void)bridgeInMRC { // 將Foundation物件轉換為Core Foundation物件,直接強制型別轉換即可 NSString *strOC1 = [NSString stringWithFormat:@"xxxxxx"]; CFStringRef strC1 = (CFStringRef)strOC1; NSLog(@"%@ %@", strOC1, strC1); [strOC1 release]; CFRelease(strC1); // 將Core Foundation物件轉換為Foundation物件,直接強制型別轉換即可 CFStringRef strC2 = CFStringCreateWithCString(CFAllocatorGetDefault(), "12345678", kCFStringEncodingASCII); NSString *strOC2 = (NSString *)strC2; NSLog(@"%@ %@", strOC2, strC2); [strOC2 release]; CFRelease(strC2); }
2.2 ARC下的轉換
ARC僅管理Objective-C指標(retain、release、autorelease),不管理CoreFoundation指標。CF指標由人工管理,手動的CFRetain和CFRelease來管理。
在ARC中,CF和OC之間的轉化橋樑是 __bridge,有3種方式:
__bridge
只做型別轉換,不改變物件所有權,是我們最常用的轉換符。__bridge_transfer
:ARC接管 管理記憶體__bridge_retained
:ARC釋放 記憶體管理
2.3 簡單互相轉換:__bridge
① 從OC轉CF,ARC管理記憶體:
(__bridge CFStringRef)
需要人工CFRetain,否則,Cocoa指標釋放後, 傳出去的指標則無效。
例子
- (void)viewDidLoad { [super viewDidLoad]; NSString *aNSString = [[NSString alloc]initWithFormat:@"test"]; CFStringRef aCFString = (__bridge CFStringRef)aNSString; (void)aCFString; }
上面只是單純地執行了型別轉換,沒有進行所有權的轉移,也就是說,當aNSString物件被ARC釋放的時候,aCFString也不能被使用了。
② 從CF轉OC,需要開發者手動釋放,不歸ARC管:
(__bridge NSString *)
需要人工CFRelease,否則,OC物件的指標釋放後,物件引用計數仍為1,不會被銷燬。
例子
- (void)viewDidLoad { [super viewDidLoad]; CFStringRef aCFString = CFStringCreateWithCString(NULL, "test", kCFStringEncodingASCII); NSString *aNSString = (__bridge NSString *)aCFString; (void)aNSString; CFRelease(aCFString); }
3. ARC下記憶體管理發生改變的轉換
3.1 CF-->OC:__bridge_transfer
例子
- (void)viewDidLoad { [super viewDidLoad]; NSString *aNSString = [[NSString alloc]initWithFormat:@"test"]; CFStringRef aCFString = (__bridge_retained CFStringRef) aNSString; aNSString = (__bridge_transfer NSString *)aCFString; }
3.2 OC-->CF:__bridge_retained
例子
- (void)viewDidLoad { [super viewDidLoad]; NSString *aNSString = [[NSString alloc]initWithFormat:@"test"]; CFStringRef aCFString = (__bridge_retained CFStringRef) aNSString; (void)aCFString; //這時候,即使開啟ARC,也需要手動執行CFRelease CFRelease(aCFString); }
3.3 怎麼區分記憶?
因為ARC無法管理CF物件的指標,所以,無論是CF轉OC還是OC轉CF,我們只需關心CF物件的引用需要加1還是減1即可。
CF轉OC:CFRef必須減1
這樣原來的CF物件就被釋放,所以,以後也不用手動釋放。
NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
OC轉CF:CFRef 必須加1
這樣新的CF物件就不會被釋放,所以,以後用完必須手動釋放。
CFStringRef d = (__bridge_retained CFStringRef)my_id; // returned CFRef is +1
//這時候,即使開啟ARC,CF物件用完後也需要手動執行CFRelease CFRelease(aCFString);
3.4 轉換相關的宏
CFBridgingRetain
NS_INLINE CFTypeRef CFBridgingRetain(id X) { return (__bridge_retain CFTypeRef)X; }
CFBridgingRelease
NS_INLINE id CFBridgingRelease(CFTypeRef X) { return (__bridge_transfer id)X; }
例1
下面兩個等效
CFStringRef cfStr = (__bridge_retained CFStringRef)ocStr;
CFStringRef cfStr = CFBridgingRetain(ocStr);
例2
下面兩個等效
NSString *ocStr = (__bridge_transfer NSString*)cfStr;
NSString *ocStr = CFBridgingRelease(cfStr);
3.5 總結
CF轉化為OC時,並且物件的所有者發生改變,則使用
CFBridgingRelease()
或__bridge_transfer
。OC轉化為CF時,並且物件的所有者發生改變,則使用
CFBridgingRetain()
或__bridge_retained
作者:陳滿iOS
連結:
來源:簡書
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/132/viewspace-2808898/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS引用轉換:Foundation與Core Foundation物件互相轉換(__CFString轉NSString,void *轉id等等)iOS物件
- CS 839: FOUNDATION MODELS
- 瞭解下Foundation JoyrideIDE
- 瞭解下Foundation 表格
- 瞭解下Foundation 按鈕
- 微軟workflow foundation介紹微軟
- Foundation 價格表簡介
- 瞭解下Foundation 按鈕組
- 編譯開源 Swift Foundation 庫編譯Swift
- 瞭解下Foundation 均衡器(Equalizer)
- 瞭解下Foundation 網格系統
- 瞭解下Foundation 網格例項
- Apache資源(Apache Software Foundation Distribution Directory)Apache
- 【VMware VCF】VMware Cloud Foundation Part 01:概述。Cloud
- PHP 基金會,是個好事 (PHP Foundation)PHP
- 瞭解下Foundation 網格 – 大型裝置
- 什麼是 SAP C/4HANA Foundation
- 日呼叫量超600億次,HMS Core HiAI Foundation助力AI應用高效開發AI
- 初識AV Foundation-視訊、影象採集
- 【VMware VCF】VMware Cloud Foundation Part 02:部署 Cloud Builder。CloudUI
- 什麼是人工智慧領域的 Foundation Model?人工智慧
- 【VMware VCF】VMware Cloud Foundation Part 05:部署 SDDC 管理域。Cloud
- 【VMware VCF】VMware Cloud Foundation Part 04:準備 ESXi 主機。Cloud
- 端側AI進化論:HUAWEI HiAI Foundation的奇妙旅程AI
- 藉助Unity AR Foundation構建跨平臺AR應用Unity
- VMware Private AI Foundation with NVIDIA - 生成式人工智慧解決方案AI人工智慧
- 【VMware VCF】使用 PowerVCF 連線和管理 VMware Cloud Foundation 環境。Cloud
- 【VMware VCF】VMware Cloud Foundation Part 06:部署 VI 工作負載域。Cloud負載
- 【VMware VCF】VMware Cloud Foundation Part 03:準備 Excel 參數列。CloudExcel
- APENFT FOUNDATION官宣2022藝術夢想基金主題徵集
- POLIR-Society-Organization-Psychology-Color Theory:色彩理論 of IxDF(Interaction Design Foundation)
- 一萬年太久,只爭朝夕 | Foundation model的進展仍不夠快
- Veritas Storage Foundation for Oracle RAC(VCS4.0 + VxVM4.0 ..)安裝過程Oracle
- HiAI Foundation開發平臺,加速端側AI應用的智慧革命AI
- Nocalhost 亮相 CD Foundation 國內首屆 Meetup,Keith Chan 將出席致辭
- C++ 左值引用和右值引用之間的轉換C++
- The Mellon Foundation:2022年北美藝術館機構員工調查報告
- Web Foundation:調查顯示全球仍有數十億人買不起智慧手機Web