簡介
Core Foundation 是一組慨念源自O(shè)C基礎(chǔ)框架的編程接口,并使用c語言實(shí)現(xiàn)的庫.為了實(shí)現(xiàn)這個(gè)庫,Core Foundation用C語言實(shí)現(xiàn)一個(gè)限制對(duì)象模型.Core Foundation定義不透明類型來封裝數(shù)據(jù)和函數(shù),之后就稱他們?yōu)?對(duì)象".
Core Foundation對(duì)象設(shè)計(jì)的編程接口具有易用性和可復(fù)用性.在普通層次下,Core Foundation有以下特性:
- 能夠在繁雜多樣的框架和庫中共享數(shù)據(jù)和代碼
- 使得在一定程度上獨(dú)立于操作系統(tǒng)成為可能
- 支持使用unicode字符串的國際化
- 提供一些API和其他有用的功能,包括一個(gè)插件架構(gòu),XML屬性列表等
Core Foundation使OS X上不同的框架和庫共享代碼與數(shù)據(jù)成為可能.應(yīng)用,庫,框架讓你在平常C編程中删咱,定義混合Core Foundation類型的接口虹曙;因此,它們可以計(jì)算數(shù)據(jù)--就像Core Foundation對(duì)象--通過這些接口設(shè)計(jì)算各自的數(shù)據(jù).
Core Foundation在已確定的服務(wù)和Cocoa的Foundation框架之間提供"toll-free bridging"(無代價(jià)橋接). toll-free bridging能將函數(shù)參數(shù)中的Core Foundation對(duì)象替換成Cocoa對(duì)象或者反過來.
一些Core Foundation類型和函數(shù)是在不同操作系統(tǒng)上特定代碼實(shí)現(xiàn)的抽象. 使用這些API能更容易適配不同平臺(tái).
date與number類型抽象了時(shí)間工具,并提供絕對(duì)時(shí)間和公歷時(shí)間的之間的轉(zhuǎn)換工具.它還抽象了數(shù)字值,并為這些內(nèi)部表示不同的值提供的互轉(zhuǎn)工具.
Core Foundation給應(yīng)用開發(fā)帶來其中一個(gè)主要的好處是支持國際化.通過框架中的字符串對(duì)象,Core Foundation使國際化在OS X與Cocoa上接口的編寫與實(shí)現(xiàn)變得更簡單,健壯和一致.這個(gè)特性的本質(zhì)部分是一種類型--CFString, 代表一個(gè)16bit的Unicode字符數(shù)組. CFString對(duì)象能靈活地支持百萬字節(jié)的字符, 且使用一些足夠簡單的低層的接口就能計(jì)算字符數(shù)據(jù).它達(dá)到了跟與之關(guān)聯(lián)的標(biāo)準(zhǔn)C字符串差不多的性能.
你應(yīng)該閱讀這個(gè)文檔來了解Core Foundation之下的基本設(shè)計(jì)原則和Core Foundation對(duì)象跟Cocoa(Touch)對(duì)象之間的交互.
不透明類型
Core Foundation對(duì)象模型基于不透明類型,且支持封裝和多態(tài)函數(shù).
基于不透明類型的對(duì)象的各個(gè)字段隱藏于客戶端,但是這些類型的函數(shù)能提供大多數(shù)字段值.Figure 1 描繪了不透明類型所隱藏的數(shù)據(jù)且僅展示其接口給客戶端.
Note: "Class"不是用來指向不透明類型的,盡管類和不透明類型概念上相似,可很多人可能被這個(gè)詞混淆.然而,Core Foundation文檔所指的類型是特定的,這些類型的數(shù)據(jù)承載實(shí)例就稱之為"對(duì)象"
Core Foundation有很多不透明類型,而且它們的名字說明了它們的預(yù)期用途.例如,CFString
是一個(gè)用來"展示"和操作Unicode字符數(shù)組的不透明類型(CF是Code Foundation的前綴). CFArray
是基于下標(biāo)的泛型集合.一個(gè)不透明類型支持的函數(shù),常量和其他次要的數(shù)據(jù)類型通常定義在其類型對(duì)應(yīng)名字的頭文件中.例如CFArray.h
,CFArray
包含定義符號(hào).
不透明類型的優(yōu)點(diǎn)
部分情況下,一個(gè)不透明類型似乎要通過令人沮喪的結(jié)構(gòu)內(nèi)容直接存取來增加一些沒有必要的限制. 此外亿鲜,似乎不透明的類型可能會(huì)影響項(xiàng)目性能相關(guān)的開銷.但是不透明類型的好處要大于這些表面的局限性.
不透明類型為底層功能的實(shí)現(xiàn)提供更好的靈活性和抽象性.通過隱藏結(jié)構(gòu)字段的詳細(xì)信息,Core Foundation減少發(fā)在客戶端(Xcode)編碼時(shí),字段詳情被更改后代碼出錯(cuò)的幾率.此外,如果暴露不透明類型并允許優(yōu)化,可能會(huì)造成困惑(譯注: 其他人可能看不懂其優(yōu)化代碼,還不如封裝起來).例如CFString
"正式"代表UniChar
的16bit字符數(shù)組.然而, CFString
可能選擇儲(chǔ)存一個(gè)ASCII范圍內(nèi)8bit數(shù)值的字符串.復(fù)制一個(gè)不可變的對(duì)象可能(經(jīng)常發(fā)生)導(dǎo)致共同引用一個(gè)對(duì)象而不是內(nèi)存中兩個(gè)獨(dú)立的對(duì)象.(查看Core Foundation內(nèi)存管理編程指南).
繼續(xù)CFString
這個(gè)例子,使用一個(gè)不透明類型來儲(chǔ)存字符似乎太笨重.事實(shí)證明,并不是這樣的,CPU消耗的資源比使用簡單的C字符數(shù)組高不了多少,況且經(jīng)常比他們低.另外,不透明并不一定說明這一個(gè)不透明類型從不提供直接訪問內(nèi)容的機(jī)制.CFString
,對(duì)于它的實(shí)例,提供了CFStringGetCStringPtr
函數(shù)來直接訪問.
最后,你可以在一定的程度上自定義一些不透明類型.例如,集合類型允許為集合的每一個(gè)成員上為喚醒函數(shù)定義一個(gè)回調(diào).集合類型允許調(diào)用函數(shù)時(shí)定義一個(gè)回調(diào)(譯注:callback,可以理解為函數(shù)指針),并讓每個(gè)集合成員調(diào)用.
對(duì)象引用
你可以通過引用來指向一個(gè)Core Foundation對(duì)象(不透明類型).對(duì)于頭文件的中的每一個(gè)不透明類型,你將會(huì)注意到一行或兩行相似的,類似下面的語句:
typedef const struct __CFArray * CFArrayRef;
typedef struct __CFArray * CFMutableArrayRef;
聲明這些指針指向(私有的)不可變和可變版本的結(jié)構(gòu).Core Foundation中許多函數(shù)的參數(shù)和返回值采用對(duì)象引用類型,而且從不使用typedef
私有結(jié)構(gòu)的類型. 例如:
CFStringRef CFStringCreateByCombiningStrings(CFAllocatorRef alloc, CFArrayRef array, CFStringRef separatorString);
查看 對(duì)象的種類獲取更多信息,可變的的還有其他種類的不透明對(duì)象.
每一個(gè)Core Foundation不透明類型給他們的對(duì)象定義一個(gè)唯一類型ID,如在CFArray
對(duì)象上的CFArrayRef
.類型ID是類型為CFTypeID
的整型,這個(gè)ID標(biāo)識(shí)了一個(gè)Core Foundation所屬的不透明類型.在各種上下文中使用類型ID, 如在你操作各式各樣的容器時(shí)使用.Core Foundation提供一些編程性接口,用于獲取和計(jì)算類型ID的值.
重要:由于類型ID的值可以隨著版本的變化而變化,你的類型ID應(yīng)該不能依賴已保存的或?qū)懰赖念愋虸D,也不應(yīng)該被任何能觀察到的屬性賦值(例如賦給它一個(gè)簡單的整形:23333).
另外,Core Foundation定義了一個(gè)通用的對(duì)象引用(object-reference)類型, CFTypeRef
,類似其他面向?qū)ο笳Z言的基(root)類.這個(gè)通用的引用作為一個(gè)多態(tài)函數(shù)的參數(shù)與返回值的占位符類型,可以指向任何Core Foundation對(duì)象.查看多態(tài)函數(shù)獲取更多關(guān)于這個(gè)課題的信息.查看Core Foundation的內(nèi)存管理指南討論使用對(duì)象引用時(shí)內(nèi)存管理的相關(guān)問題.
多態(tài)函數(shù)
Core Foundation提供一些多態(tài)函數(shù),這些函數(shù)可以將任意Core Foundation對(duì)象作為參數(shù)和(有一個(gè)例子:CFRetain
)可以返回任意Core Foundation對(duì)象.這些參數(shù)和返回值的類型是CFTypeRef
,是一個(gè)通用的對(duì)象引用(object-reference)類型.CFType
是類似于其他面向?qū)ο笳Z言中的根類,因?yàn)樗暮瘮?shù)可以被其他所有對(duì)象復(fù)用.
你可以使用多態(tài)函數(shù)對(duì)所有的Core Foundation對(duì)象進(jìn)行一些通用操作:
- 引用計(jì)數(shù)
CFType
提供幾個(gè)多態(tài)函數(shù)來計(jì)算和獲取對(duì)象的引用計(jì)數(shù).查看Core Foundation的內(nèi)存管理指南獲取更多的關(guān)于這些函數(shù)的信息. - 比較對(duì)象
CFEqual
函數(shù)能比較任何兩個(gè)Core Foundation對(duì)象(查看比較對(duì)象).等式成立的基本條件取決于同類型對(duì)象的比較.例如,如果比較兩個(gè)CFString
對(duì)象,該測試涉及逐個(gè)字符的比較. - 哈希對(duì)象
CFHash
函數(shù)返回一個(gè)唯一的能夠標(biāo)識(shí)Core Foundation對(duì)象的哈希碼(查看比較對(duì)象).你可以把哈希碼當(dāng)哈希表數(shù)據(jù)結(jié)構(gòu)中的表地址.如果兩個(gè)對(duì)象相等(由CFEqual
函數(shù)決定),他們必須有相同的哈希值. - 核查對(duì)象
CFType
提供核查對(duì)象的函數(shù),從而了解它們的內(nèi)容以及他們"所屬"的類型.CFCopyDescription
函數(shù)返回一個(gè)描述該對(duì)象的字符串(更切確地說,是一個(gè)CFString
對(duì)象的引用).CFCopyTypeIDDescription
函數(shù)需要提供一個(gè)CFTypeID
參數(shù)而不是CFTypeRef
.這個(gè)函數(shù)返回一個(gè)描述標(biāo)識(shí)一個(gè)不透明類型的類型ID的字符串引用.這些函數(shù)主要用來協(xié)助調(diào)試.查看核查對(duì)象獲取更多相關(guān)的函數(shù).
你還可以通過CFGetTypeID
函數(shù)獲得不透明對(duì)象的類型ID,通過這個(gè)ID決定一個(gè)通用類型對(duì)象所屬的不透明類型,再將已知類型ID對(duì)應(yīng)的值相比較.查看檢查對(duì)象獲取更多關(guān)于這個(gè)任務(wù)的信息.
對(duì)象的種類
不透明類型擁有多達(dá)3種基本種類,或者"口味".(譯注:這里為了跟之前的對(duì)象類型(object type)區(qū)分,故意使用種類或'口味').基于可擴(kuò)展性和可編輯性的特點(diǎn)分為以下:
- 不可變和固定大小
- 可變和固定大小
- 可變和不固定大小
可變對(duì)象是可編輯的,意味著他們的內(nèi)容可以修改.不可變對(duì)象不能編輯的;一旦創(chuàng)建之后就無法再改變.對(duì)不可變對(duì)象的任何修改都會(huì)導(dǎo)致一些(譯注:編譯器)錯(cuò)誤.一個(gè)固定大小的可變對(duì)象有一個(gè)最大值來限制其大小的增長;就CFString
來說,一個(gè)CFString
可能是字符串中的字符個(gè)數(shù),對(duì)于一個(gè)容器來說,其限制可能是元素的數(shù)量.
一些不透明類型,例如CFString
和CFArray
,可以創(chuàng)建所有三種口味
的對(duì)象.大部分不透明類型可以創(chuàng)建不可變的,固定大小的對(duì)象,至少有一個(gè)無限制的創(chuàng)建函數(shù)來創(chuàng)建無限制對(duì)象(如CFArrayCreate
).決定可變對(duì)象的可變大小或不可變大小的是CreateMutable
函數(shù)的容量(capacity
)參數(shù)和長度最大值(maximum-length
)參數(shù);任何正整數(shù)都能生成對(duì)固定大小的對(duì)象,但是參數(shù)為0則生成一個(gè)可變大小對(duì)象.
使用帶有"Mutable"名字的類型指向可變對(duì)象,例如,CFMutableStringRef
.
命名約定
Core Foundation中主要編程接口的約定是使用不透明類型的名字中最密切相關(guān)的符號(hào)作為符號(hào)的前綴.對(duì)于函數(shù),這個(gè)前綴不僅標(biāo)識(shí)這該函數(shù)"屬于"那個(gè)類型,而且經(jīng)常用來標(biāo)識(shí)函數(shù)動(dòng)作(action)的目標(biāo)(target)對(duì)象的類型(type).(有一個(gè)例外是那些以k
作為前綴的常量).在頭文件中有一些例子:
/* from CFDictionary.h */
CF_EXPORT CFIndex CFDictionaryGetCountOfKey(CFDictionaryRef dict, const void *key);
/* from CFString.h */
typedef UInt32 CFStringEncoding;
/* from CFCharacterSet.h */
typedef enum {
kCFCharacterSetControl = 1,
kCFCharacterSetWhitespace,
kCFCharacterSetWhitespaceAndNewline,
kCFCharacterSetDecimalDigit,
kCFCharacterSetLetter,
kCFCharacterSetLowercaseLetter,
kCFCharacterSetUppercaseLetter,
kCFCharacterSetNonBase,
kCFCharacterSetDecomposable,
kCFCharacterSetAlphaNumeric,
kCFCharacterSetPunctuation,
kCFCharacterSetIllegal
} CFCharacterSetPredefinedSet;
除上述之外,Core Foundation中有一小部分編程接口約定是有關(guān)于不透明類型和內(nèi)存管理的.
Get,Copy和Create之間有著很重大的區(qū)別,在于函數(shù)的返回值的命名.如果你使用Get函數(shù),只是無法確定對(duì)象的生命周期.為了確保對(duì)象能夠持續(xù)存在,你可以持有(retain)它(使用
CFRetain
函數(shù)),或者在一些情況下,復(fù)制(copy)一份.如果你使用Copy或Create函數(shù),你必須負(fù)責(zé)釋放對(duì)象(使用CFRelease
函數(shù)).更多詳情請(qǐng)查看Core Foundation內(nèi)存管理指南-
部分Core Foundation對(duì)象有它們自己的命名約定,并以此加強(qiáng)通用操作的一致性.例如,集合(collection)將下列動(dòng)詞嵌入函數(shù)名,已表示集合中的元素的特定操作.
-
Add
意味'如果存在就添加,如果存在就不做任何事'(針對(duì)某一個(gè)集合實(shí)例) -
Replace
意味'如果存在就替換,如果不存在就不做任何事' -
Set
意味'如果不存在就添加,如果存在就替換' -
Remove
意味'如果存在就刪除,如果不存在就不做任何事'
-
CFIndex
類型用于下標(biāo)(index),計(jì)數(shù)(count),長度(length),和大小(size),并作為函數(shù)的參數(shù)或者返回值.這個(gè)類型(整形)的值(當(dāng)前是32位),可以隨著處理器地址大小的增長而增長.在指針大小不同的架構(gòu)上,如果是64位處理器,CFIndex可能是64位,這取決于int
的大小.在Core Foundation參數(shù)中使用相同類型CFIndex
的變量進(jìn)行交互,可以確保您的代碼有更高的源碼兼容性.一些Core Foundation頭文件似乎定義不透明類型,但實(shí)際上卻包含便利函數(shù)而不是關(guān)聯(lián)一些特定的類型.恰當(dāng)?shù)睦邮?code>CFPropertyList.h.
CFPropertyList
是下列屬性列表類型中任意一個(gè)類型的占位符類型:CFString
,CFDate
,CFBoolean
,CFNumber
,CFDate
,CFArray
和CFDictionary
.除非特殊說明,否則所有傳遞引用參數(shù)并打算返回值都可以接受
NULL
.這表明調(diào)用者不需要關(guān)心函數(shù)的返回值.
其他類型
Core Foundation定義若干個(gè)數(shù)據(jù)類型,并在函數(shù)中使用.這些類型存在的目的是抽象原始值.這個(gè)原始值可能隨處理器地址空間改變而改變.例如CFIndex
類型,應(yīng)用于下標(biāo)(index), 計(jì)數(shù)(count),長度(length),和大小(size)參數(shù).CFOptionFlags
類則用于位字段參數(shù),CFHashCode
類型包含從CFHash
函數(shù)和已確定的哈吓捕回調(diào)中返回的哈希結(jié)果.
其他基本類型用于傳入函數(shù)和函數(shù)返回的比較值與范圍值.CFRange
是一個(gè)指定線性隊(duì)列的任意一部分的結(jié)構(gòu),從字符串中的數(shù)組到集合中的元素.對(duì)于比較函數(shù),CFComparisonResult
類型定義枚舉常量來代表適當(dāng)?shù)姆祷刂?等于,小于,大于).部分Core Foundation函數(shù)傳入一個(gè)回調(diào)到比較函數(shù)中去;如果你需要自定義比較操作,函數(shù)必須符合CFComparatorFunction
中指定的類型(譯注:函數(shù)的參數(shù)必須與(const void *val1, const void *val2, void *context)相同).
重要: 只要其值是整形值,那么其類型一定是Core Foundation類型,特別是
CFIndex
和CFTypeID
,可以隨著處理器尋址大小的增長而增長.在Core Foundation參數(shù)中使用相同類型CFIndex
的變量進(jìn)行交互,可以讓確保您的代碼有更高的源碼兼容性.
Core Foundation中體統(tǒng)的其他不透明類型在其他主題中討論.
比較對(duì)象
你可用CFEqual
函數(shù)來比較兩個(gè)Core Foundation對(duì)象.如果兩個(gè)對(duì)象在本質(zhì)上是相等的,函數(shù)將返回一個(gè)boolean
類型的true
值."本質(zhì)上"相等取決于相同類型的對(duì)象的比較.當(dāng)你比較兩個(gè)CFString
對(duì)象,不管他們的編碼和是否可變,當(dāng)他們逐個(gè)字符完全匹配時(shí), Core Foundation則認(rèn)為他們本質(zhì)上相等.兩個(gè)CFArray
對(duì)象比較,當(dāng)它們有相同數(shù)量的元素和數(shù)組中每一個(gè)元素對(duì)象與對(duì)應(yīng)數(shù)組中的元素本質(zhì)上相等,這時(shí)會(huì)認(rèn)為他們本質(zhì)上相等.很明顯,比較對(duì)象必須是相同類型(不管可變或不可變)才會(huì)認(rèn)為是相等的.
下面代碼片段給你展示了可能使用CFEqual
函數(shù)比較一個(gè)常量與傳入?yún)?shù)是否相等.
Listing 1 比較Core Foundation對(duì)象
void stringTest(CFStringRef myString) {
Boolean equal = CFEqual(myString, CFSTR(“Kalamazoo”));
if (!equal) {
printf(“They’re not equal!");
}
else {
printf(“They’re equal!”):
}
}
核查對(duì)象
Core Foundation對(duì)象的主要特征是它們都基于一個(gè)不透明(或私有)類型;可能因此難以直接核查對(duì)象的內(nèi)部數(shù)據(jù).然而,基礎(chǔ)服務(wù)提供了兩個(gè)函數(shù)來檢查Core Foundation對(duì)象.這些函數(shù)返回對(duì)象及對(duì)象類型的描述信息.
為了找出Core Foundation對(duì)象的內(nèi)容,調(diào)用CFCopyDescription
函數(shù)并傳進(jìn)其對(duì)象.然后打印所引用的字符串對(duì)象所"包含"的字符序列.
Listing 1 使用CFCopyDescription
void describe255(CFTypeRef tested) {
char buffer[256];
CFIndex got;
CFStringRef description = CFCopyDescription(tested);
CFStringGetBytes(description,
CFRangeMake(0, CFStringGetLength(description)),
CFStringGetSystemEncoding(), '?', TRUE, buffer, 255, &got);
buffer[got] = (char)0;
fprintf(stdout, "%s", buffer);
CFRelease(description);
}
這個(gè)例子顯示了一種打印描述信息(description)的途徑.你不應(yīng)該使用CFStringGetBytes
,而是使用CFString
函數(shù)來獲取真正的字符串.
為了確定一個(gè)"未知"對(duì)象的類型,用CFGetTypeID
函數(shù)取得它的類型ID,將值與已知的類型ID進(jìn)行比較,直到匹配.可以使用CFGetTypeID
獲取一個(gè)對(duì)象的類型ID.每一個(gè)不透明類型還定義了一個(gè)CFTypeGetTypeID
表格的函數(shù)(例如CFArrayGetTypeID
);這個(gè)函數(shù)返回給定類型的類型ID.在此之前,你可以測試一下一個(gè)CFType
對(duì)象是否是指定不透明類型的成員.
CFTypeID type = CFGetTypeID(anObject);
if (CFArrayGetTypeID() == type)
printf(“anObject is an array.”);
else
printf(“anObject is NOT an array.”);
為了打印Core Foundation對(duì)象的類型在調(diào)試狀態(tài)下的相關(guān)信息.使用CFGetTypeID
函數(shù)來獲取這個(gè)類型ID,然后通過這個(gè)值傳入CFCopyTypeIDDescription
函數(shù):
/* aCFObject is any Core Foundation object */
CFStringRef descrip = CFCopyTypeIDDescription(CFGetTypeID(aCFObject));
注意: 字符串基礎(chǔ)功能中包含兩個(gè)函數(shù):
CFShow
和CFShowStr
,都聲明在CFString.h
頭文件中.在調(diào)試模式下,你可以調(diào)用它們打印Core Foundation的描述.
重要:
CFCopyDescription
和CFCopyTypeIDDescription
只在調(diào)試模式下使用.不要?jiǎng)?chuàng)建任何依賴它們的代碼,因?yàn)槊枋鲂畔⑴c他們的格式隨時(shí)改變.
無代價(jià)橋接類型
在Core Foundation框架與Foundation框架中有若干可相互轉(zhuǎn)換的數(shù)據(jù)類型.可相互裝換的數(shù)據(jù)類型也被稱為無代價(jià)橋接(toll-free bridged)數(shù)據(jù)類型.這意味著你可以使用相同的數(shù)據(jù)結(jié)構(gòu)作為參數(shù)傳進(jìn)Core Foundation調(diào)用的函數(shù)和作為一個(gè)Objective-C消息發(fā)送的接收器.例如,NSLocale
(查看NSLocale Class Reference), 與之對(duì)應(yīng)的Core Foundation的CFLocal
(查看CFLocale)是可相互轉(zhuǎn)換的.
不是所有的數(shù)據(jù)類型都是無代價(jià)橋接的,甚至通過他們的名字可能猜得出他們是有代價(jià)橋接的.例如NSRunLoop
轉(zhuǎn)換到CFRunLoop
不是無代價(jià)橋接,NSBundle
轉(zhuǎn)換至CFBundle
不是無代價(jià)橋接.NSDateFormate
轉(zhuǎn)換到CFDateFormatter
也不是.table 1提供了一張?zhí)峁┑臒o條件橋接的表.
注意: 在你使用corefoundation的集合時(shí),如果安裝(install)一個(gè)自定義回調(diào)(call back),包括
NULL
回調(diào).從Objective-C訪問時(shí),該自定義回調(diào)的內(nèi)存管理的行為是沒有定義的.
強(qiáng)制類型轉(zhuǎn)換和對(duì)象生命期的語義(Casting and Object Lifetime Semantics)
通過無條件橋接,當(dāng)你在一個(gè)方法中,看到有些參數(shù),例如NSLocale *
參數(shù),可以傳進(jìn)一個(gè)CFLocaleRef
;在函數(shù)看到CFLocaleRef
參數(shù),你可以傳一個(gè)NSLocale
實(shí)例.不過你必須為編譯器提供其他信息: 首先, 將一個(gè)類型強(qiáng)制轉(zhuǎn)換(cast)為其他類型;另外,你可能還要指示出對(duì)象的聲明期語義.
編譯器理解Objective-C方法返回的Core Foundation類型和遵循過去Cocoa命名約定(查看高級(jí)內(nèi)存管理編程指南).例如,編譯器知道在iOS中,通過UIColor
本身并沒有CGColor
方法來返回一個(gè)CGColor
. 你必須使用適當(dāng)?shù)膹?qiáng)制類型轉(zhuǎn)換(cast),就像下面所展示的:
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
編譯器不會(huì)自動(dòng)管理Core Foundation對(duì)象的生命期.選擇強(qiáng)制類型轉(zhuǎn)換(cast)(在objc/runtime.h
中定義)和Core Foundation風(fēng)格的宏(在NSObject.h
中定義)其中一個(gè),告訴編譯器關(guān)于對(duì)象的持有者.
__bridge
將一個(gè)指向Objective-C與Core Foundation兩者之一的指針相互轉(zhuǎn)換,沒有轉(zhuǎn)換持有權(quán).__bridge_retained
或CFBridgingRetain
強(qiáng)制類型轉(zhuǎn)換(cast)指向Objective-C的指針為Core Foundation指針并把持有權(quán)轉(zhuǎn)給你.
你負(fù)責(zé)調(diào)用CFRelease
或相關(guān)函數(shù)來放棄對(duì)象的持有權(quán).-
__bridge_transfer
或CFBridgingRelease
移動(dòng)一個(gè)非Objective-C指針到Objective-C,并且將對(duì)象持有權(quán)交給ARC.
ARC 有負(fù)責(zé)放棄對(duì)象的持有權(quán).
上述看起來就像下面這個(gè)例子:NSLocale *gbNSLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]; CFLocaleRef gbCFLocale = (__bridge CFLocaleRef)gbNSLocale; CFStringRef cfIdentifier = CFLocaleGetIdentifier(gbCFLocale); NSLog(@"cfIdentifier: %@", (__bridge NSString *)cfIdentifier); // Logs: "cfIdentifier: en_GB" CFLocaleRef myCFLocale = CFLocaleCopyCurrent(); NSLocale *myNSLocale = (NSLocale *)CFBridgingRelease(myCFLocale); NSString *nsIdentifier = [myNSLocale localeIdentifier]; CFShow((CFStringRef)[@"nsIdentifier: " stringByAppendingString:nsIdentifier]);
下一個(gè)例子展示Core Foundation內(nèi)存管理函數(shù)的用法.這些函數(shù)由Core Foundation內(nèi)存管理規(guī)則主宰:
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat locations[2] = {0.0, 1.0};
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object.
CGPoint startPoint = CGPointMake(0.0, 0.0);
CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));
CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint,
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient); // Release owned Core Foundation object.
}
無代價(jià)橋接類型
table 1 提供一個(gè)可在Core Foundation和Foundation之間相互裝換的數(shù)據(jù)類型的列表.對(duì)于每一對(duì),表中來列舉了它們之間無代價(jià)橋接變得有效時(shí)OS X的版本.
Table 1 在Core Foundation和Foundation之間相互裝換的數(shù)據(jù)類型
Core Foundation type | Foundation Class | Availability |
---|---|---|
CFArrayRef | NSArray | OS X v10.0 |
CFAttributedStringRef | NSAttributedString | OS X v10.4 |
CFCalendarRef | NSCalendar | OS X v10.4 |
CFCharacterSetRef | NSCharacterSet | OS X v10.0 |
CFDataRef | NSData | OS X v10.0 |
CFDateRef | NSDate | OS X v10.0 |
CFDictionaryRef | NSDictionary | OS X v10.5 |
CFErrorRef | NSError | OS X v10.5 |
NSLocale | NSLocale | OS X v10.4 |
CFMutableArrayRef | NSMutableArray | OS X v10.0 |
CFMutableAttributedStringRef | NSMutableAttributedString | OS X v10.4 |
CFMutableCharacterSetRef | NSMutableCharacterSet | OS X v10.0 |
CFMutableDataRef | NSMutableData | OS X v10.0 |
CFMutableDictionaryRef | NSMutableDictionary | OS X v10.0 |
CFMutableSetRef | NSMutableSet | OS X v10.0 |
CFMutableStringRef | NSMutableString | OS X v10.0 |
CFNumberRef | NSNumber | OS X v10.0 |
CFReadStreamRef | NSInputStream | OS X v10.0 |
CFRunLoopTimerRef | NSTimer | OS X v10.0 |
CFSetRef | NSSet | OS X v10.0 |
CFStringRef | NSString | OS X v10.0 |
CFTimeZoneRef | NSTimeZone | OS X v10.0 |
CFURLRef | NSURL | OS X v10.0 |
CFWriteStreamRef | NSOutputStream | OS X v10.0 |