[譯]iOS Core Foundation Design Concepts

本文翻譯: Core Foundation design concept

簡介

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

Figure 1  An opaque type
Figure 1 An opaque type

不透明類型的優(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ù)量.
一些不透明類型,例如CFStringCFArray,可以創(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,CFArrayCFDictionary.

  • 除非特殊說明,否則所有傳遞引用參數(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類型,特別是CFIndexCFTypeID,可以隨著處理器尋址大小的增長而增長.在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ù):CFShowCFShowStr,都聲明在CFString.h頭文件中.在調(diào)試模式下,你可以調(diào)用它們打印Core Foundation的描述.

重要: CFCopyDescriptionCFCopyTypeIDDescription只在調(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_retainedCFBridgingRetain強(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_transferCFBridgingRelease移動(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市渐夸,隨后出現(xiàn)的幾起案子箍镜,更是在濱河造成了極大的恐慌源祈,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件色迂,死亡現(xiàn)場離奇詭異香缺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)歇僧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門图张,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事祸轮∈薨#” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵适袜,是天一觀的道長柄错。 經(jīng)常有香客問我,道長苦酱,這世上最難降的妖魔是什么鄙陡? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮躏啰,結(jié)果婚禮上趁矾,老公的妹妹穿的比我還像新娘。我一直安慰自己给僵,他們只是感情好毫捣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帝际,像睡著了一般蔓同。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹲诀,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天斑粱,我揣著相機(jī)與錄音,去河邊找鬼脯爪。 笑死则北,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痕慢。 我是一名探鬼主播尚揣,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼掖举!你這毒婦竟也來了快骗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤塔次,失蹤者是張志新(化名)和其女友劉穎方篮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體励负,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡藕溅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熄守。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜈垮。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耗跛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出攒发,到底是詐尸還是另有隱情调塌,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布惠猿,位于F島的核電站羔砾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏偶妖。R本人自食惡果不足惜姜凄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趾访。 院中可真熱鬧态秧,春花似錦、人聲如沸扼鞋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽云头。三九已至捐友,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溃槐,已是汗流浹背匣砖。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昏滴,地道東北人猴鲫。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像影涉,于是被迫代替她去往敵國和親变隔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 版本記錄 前言 Core Foundation框架(CoreFoundation.framework)是一組C語言...
    刀客傳奇閱讀 2,605評(píng)論 0 3
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,125評(píng)論 29 470
  • 序言 目前形勢蟹倾,參加到iOS隊(duì)伍的人是越來越多,甚至已經(jīng)到供過于求了猖闪。今年鲜棠,找過工作人可能會(huì)更深刻地體會(huì)到今年的就...
    iOS_Alex閱讀 1,615評(píng)論 1 24
  • 序言 目前形勢,參加到iOS隊(duì)伍的人是越來越多培慌,甚至已經(jīng)到供過于求了豁陆。今年,找過工作人可能會(huì)更深刻地體會(huì)到今年的就...
    麥兜兜買兜兜閱讀 671評(píng)論 1 4
  • 第1篇Objective-C準(zhǔn)備篇 第1章Objective-C學(xué)習(xí)環(huán)境準(zhǔn)備 1.1Objective-C基礎(chǔ) 1...
    YHWXQ簡簡單單的生活閱讀 1,009評(píng)論 2 2