久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

iPhone開發(fā)之深入淺出 (7) — ARC總結(jié)

 現(xiàn)在決定明天 2014-03-01

 

 

通過前面幾篇文章的介紹,,我想大家應(yīng)該對(duì)ARC有了一個(gè)比較完整的理解,。最后,我們來對(duì)ARC做一個(gè)總結(jié),,并把一些未涉及到的細(xì)節(jié)部分再深入討論一下,。

內(nèi)存管理基本原則

內(nèi)存管理的依循下面的基本原則
  • 自己生成的對(duì)象,那么既是其持有者
  • 不是自己生成的對(duì)象,,也可成為其持有者(一個(gè)對(duì)象可以被多個(gè)人持有)
  • 如果不想持有對(duì)象的時(shí)候,,必須釋放其所有權(quán)
  • 不能釋放已不再持有所有權(quán)的對(duì)象

    不管ARC有沒有效,該原則始終存在,。

所有權(quán)關(guān)鍵字

從代碼上看,,有ARC的代碼和沒有ARC的代碼區(qū)別就在下面的幾個(gè)關(guān)鍵字,。

類似 NSObject* 的對(duì)象類型,或者 id 類型1,,當(dāng)ARC有效的時(shí)候,,根據(jù)具體情況,這些關(guān)鍵字必須要使用2,。

  • __strong
  • __weak
  • __unsafe_unretained
  • __autoreleasing

    __strong是默認(rèn)的修飾符,。

    __weak修飾了一個(gè)自動(dòng)nil的weak引用。

    __unsafe_unretained聲明了一個(gè)不會(huì)自動(dòng)nil的weak引用,。當(dāng)變量被釋放,,那么它就變成了一個(gè)野指針了。

    __autoreleasing 用來修飾一個(gè)聲明為 (id *) 的函數(shù)的參數(shù),,當(dāng)函數(shù)返回值時(shí)被釋放,。

接下來,我們結(jié)合下面ARC的使用準(zhǔn)則,,來看看一些使用ARC后的技術(shù)細(xì)節(jié),。

ARC使用準(zhǔn)則

為了避免程序秒退的尷尬,ARC有效時(shí),,我們的代碼必須遵循下面的準(zhǔn)則,。

  • 不能使用 retain/release/retainCount/autorelease
  • 不能使用 NSAllocateObject/NSDeallocateObject
  • 不能使用 NSZone
  • 不能明示調(diào)用dealloc
  • 內(nèi)存管理相關(guān)的函數(shù)必須遵循命名規(guī)則
  • 使用@autoreleasepool代替NSAutoreleasePool
  • Objective-C 對(duì)象不能作為C語言結(jié)構(gòu)體(struct/union)的成員
  • 【id】與【void*】之間需要明示cast

建議使用Objective-C的class來管理數(shù)據(jù)格式,來代替C語言的struct,。不能隱式轉(zhuǎn)換 id 和 void *,。

不能使用 retain/release/retainCount/autorelease

內(nèi)存管理完全交給編譯器去做,所以之前內(nèi)存相關(guān)的函數(shù)(retain/release/retainCount/autorelease)不能出現(xiàn)在程序中,。Apple的ARC文檔中也有下面的說明,。

ARC 有效后,不需要再次使用retain 和 release

如果我們?cè)诔绦蛑惺褂眠@些函數(shù),,經(jīng)得到類似下面的編譯錯(cuò)誤信息,。

    error: ARC forbids explicit message send of ’release’
         [o release];
          ^ ~~~~~~~

不能使用 NSAllocateObject/NSDeallocateObject

生成并持有一個(gè)Objective-C對(duì)象的時(shí)候,,往往像下面一樣使用NSObject的alloc接口函數(shù),。

    id obj = [NSObject alloc];

實(shí)際上,如果我們看了GNUstep 中關(guān)于 alloc 的代碼就會(huì)明白,,實(shí)際他是使用 NSAllocateObject 來生成并持有對(duì)象實(shí)例的,。換言之,ARC有效的時(shí)候,,NSAllocateObject函數(shù)的調(diào)用也是禁止的,。如果使用,也會(huì)遇到下面的編譯錯(cuò)誤,。

    error: ’NSAllocateObject’ is unavailable:
        not available in automatic reference counting mode

同樣,,對(duì)象釋放時(shí)使用的 NSDeallocateObject 函數(shù)也不能使用,。

不能使用 NSZone

NSZone 是什么?NSZone 是為了防止內(nèi)存碎片而導(dǎo)入的一項(xiàng)措施,。Zone 是內(nèi)存管理的基本單元,,系統(tǒng)中管理復(fù)數(shù)的Zone。系統(tǒng)根據(jù)對(duì)象的使用目的,,尺寸,,分配其所屬的Zone區(qū)域。以提高對(duì)象的訪問效率,,避免不必要的內(nèi)存碎片,。但是,現(xiàn)在的運(yùn)行時(shí)系統(tǒng)(用編譯開關(guān) __OBJC2__ 指定的情況下)是不支持Zone概念的,。所以,,不管ARC是否有效,都不能使用 NSZone,。

不能明示調(diào)用dealloc

不管是否使用ARC,,當(dāng)對(duì)象被釋放的時(shí)候,對(duì)象的dealloc函數(shù)被調(diào)用(就像是C++中對(duì)象的析構(gòu)函數(shù)),。在該函數(shù)中,,需要做一些內(nèi)存釋放的動(dòng)作。比如,,當(dāng)對(duì)象中使用了malloc分配的C語言內(nèi)存空間,,那么dealloc中就需要像下面一樣處理內(nèi)存的釋放。

1
2
3
4
- (void) dealloc
{
    free(buffer_);
}

又或者是注冊(cè)的delegate對(duì)象,,觀察者對(duì)象需要被刪除的時(shí)候,,也是在dealloc函數(shù)中動(dòng)作。

1
2
3
4
- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

如果在ARC無效的時(shí)候,,我們還要像下面一樣,,調(diào)用父類對(duì)象的dealloc函數(shù)。

1
2
3
4
- (void) dealloc
{
    [super dealloc];
}

但是當(dāng)ARC有效的時(shí)候,,[super dealloc];的調(diào)用已經(jīng)被編譯器自動(dòng)執(zhí)行,,已經(jīng)不需要我們明示調(diào)用了。如果你在代碼中還這樣寫,,難免遇到下面的錯(cuò)誤,。

    error: ARC forbids explicit message send of ’dealloc’
         [super dealloc];
          ^ ~~~~~~~

內(nèi)存管理相關(guān)的函數(shù)必須遵循命名規(guī)則

iPhone開發(fā)之深入淺出 (3) — ARC之前世今生中,我們知道如果是 alloc/new/copy/mutableCopy/init 開頭的函數(shù),,需要將對(duì)象所有權(quán)返回給調(diào)用端,。這條規(guī)則不管ARC是否有效都應(yīng)該被遵守。只是 init 開頭的函數(shù)比較特殊,,他只在ARC下有要求,,而且異??量獭?/p>

init 開始的函數(shù)只能返回id型,,或者是該函數(shù)所屬的類/父類的對(duì)象類型,。基本上來說,,init函數(shù)是針對(duì)alloc函數(shù)的返回值,,做一些初始化處理,然后再將該對(duì)象返回,。比如:

    id obj = [[NSObject alloc] init];

再比如下面定義的函數(shù)就是不對(duì)的:

    - (void) initThisObject;

需要是下面這樣:

    - (id) initWithObject:(id)obj;

另外,,下面名為 initialize 的函數(shù)比較特殊,編譯器將把它過濾掉,,不按上面的規(guī)則處理,。

使用@autoreleasepool代替NSAutoreleasePool

在ARC之下,已經(jīng)不能在代碼中使用 NSAutoreleasePool,,我們之前寫 main.m 文件的時(shí)候,,往往像下面這樣寫。

1
2
3
4
5
6
    int main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

而當(dāng)ARC有效后,,我們需要用@autoreleasepool代替NSAutoreleasePool,。

1
2
3
4
5
6
int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

當(dāng)編譯器看到 @autoreleasepool 定義的塊后會(huì)自動(dòng)生成 NSAutoreleasePool 對(duì)象,并將需要的對(duì)象放入 AutoReleasePool 中,,當(dāng)出方塊的定義范圍時(shí),,pool 中的對(duì)象將被釋放。

Objective-C 對(duì)象不能作為C語言結(jié)構(gòu)體(struct/union)的成員

當(dāng)我們?cè)O(shè)置ARC有效,,并在C語言的結(jié)構(gòu)體中定義Objective-C的對(duì)象時(shí),,將出現(xiàn)類似下面的編譯錯(cuò)誤。

1
2
3
struct Data {
    NSMutableArray *array;
};
    error: ARC forbids Objective-C objs in structs or unions
         NSMutableArray *array;
                         ^

由于 ARC 是將內(nèi)存管理的細(xì)節(jié)委托給編譯器來做,,所以說編譯器必須要管理對(duì)象的生命周期,。而LLVM 3.0中不存在對(duì)單純C語言構(gòu)造體成員的內(nèi)存管理方法。如果單純是棧對(duì)象,,利用進(jìn)出棧原理,,可以簡(jiǎn)單地維護(hù)對(duì)象的生命周期;而結(jié)構(gòu)體是不行的,,簡(jiǎn)單地理解,,結(jié)構(gòu)體沒有析構(gòu)函數(shù),,編譯器自身不能自動(dòng)釋放其內(nèi)部的 Objective-C 對(duì)象,。

當(dāng)我們必須在C語言的結(jié)構(gòu)體中放入 Objective-C 對(duì)象的時(shí)候,可以使用 void* 轉(zhuǎn)型,,或者使用 __unsafe_unretained 關(guān)鍵字,。比如下面:

1
2
3
struct Data {
    NSMutableArray __unsafe_unretained *array;
};

這樣一來,,該內(nèi)存信息不在編譯器內(nèi)存管理對(duì)象內(nèi),僅僅是使用而已,,沒有對(duì)象的持有權(quán),。當(dāng)然,對(duì)象所有權(quán)的持有者需要明確的管理他與該結(jié)構(gòu)體的交互,,不要引起不必要的錯(cuò)誤3,。

【id】與【void*】之間需要明示cast

ARC 有效的時(shí)候,由于編譯器幫我們做了內(nèi)存管理的工作,,所以我們不需要太擔(dān)心,。但是當(dāng)與 ARC 管理以外的對(duì)象類型交互的時(shí)候,就需要特殊的轉(zhuǎn)型關(guān)鍵字,,來決定所有權(quán)的歸屬問題,。

主要的轉(zhuǎn)型關(guān)鍵字是:

關(guān)鍵字 解釋
__bridge 單純的類型轉(zhuǎn)換,沒有進(jìn)行所有權(quán)的轉(zhuǎn)移
__bridge_retained 類型轉(zhuǎn)換是伴隨所有權(quán)傳遞,,轉(zhuǎn)換前后變量都持有對(duì)象的所有權(quán)
__bridge_transfer 類型轉(zhuǎn)換伴隨所有權(quán)轉(zhuǎn)移,,被轉(zhuǎn)換變量將失去對(duì)象的所有權(quán)

當(dāng)我們?cè)?Core Foundation 對(duì)象類型與 Objective-C 對(duì)象類型之間切換的時(shí)候,需要把握下面的因素:

  • 明確被轉(zhuǎn)換類型是否是 ARC 管理的對(duì)象
    • Core Foundation 對(duì)象類型不在 ARC 管理范疇內(nèi)
    • Cocoa Framework::Foundation 對(duì)象類型(即一般使用到的Objectie-C對(duì)象類型)在 ARC 的管理范疇內(nèi)
  • 如果不在 ARC 管理范疇內(nèi)的對(duì)象,,那么要清楚 release 的責(zé)任應(yīng)該是誰
  • 各種對(duì)象的生命周期是怎樣的

題外話

Xcode 4.3帶來的變化

最近隨著 iOS 5.1 的推出,,Xcode也推出了4.3版本。在該版本下,,ARC 有效時(shí)的屬性(@property) 定義的時(shí)候,,如果不明確指定所有權(quán)關(guān)鍵字,那么缺省的就是 strong,。而在 Xcode4.2 中,,即使 strong 也要顯示指定。

在 Xcode4.2 的時(shí)候,,針對(duì)下面的代碼,,

1
2
3
4
5
6
7
// ARC 無效
@property (nonatomic, retain) NSString *string;

// --->

// ARC 有效
@property (nonatomic, strong) NSString *string;

而在 Xcode 4.3 中,我們可以這么做,,

1
2
3
4
5
6
7
// ARC 無效
@property (nonatomic, retain) NSString *string;

// --->

// ARC 有效
@property (nonatomic) NSString *string;

ARC 代碼自動(dòng)變換

另外,,Xcode 4.2開始,增加了舊代碼向 ARC 代碼自動(dòng)轉(zhuǎn)換的功能,。有興趣的朋友可以試試,。位置是:

Edit->Refactor->Convert to Objective-C ARC…

為什么iOS中沒有GC

我們已經(jīng)知道ARC并不是GC(垃圾回收)了,那么,,為什么iOS中不支持該機(jī)能呢,?還特意搞出個(gè)ARC來。以下是我的分析:

  • 消耗CPU時(shí)間的處理盡量避免,以節(jié)約電池電量
  • GC執(zhí)行的后,,會(huì)停掉運(yùn)行時(shí)庫(kù),;這是最大的心結(jié)
  • 嵌入式設(shè)備本身內(nèi)存就不是很大,如果GC不停的在后臺(tái)運(yùn)行,,執(zhí)行的頻率會(huì)很高,,嚴(yán)重影響性能
    • UI動(dòng)畫處理是iOS的一大賣點(diǎn),而有了GC后可能會(huì)引起不必要的性能損失

1. 關(guān)于Objective-C對(duì)象的解釋,,可以參考iPhone開發(fā)入門(7)— 從C/C++語言到Objective-C語言,。

2. 當(dāng)然,如果你不寫,,編譯器會(huì)用缺省的值代替,。具體見iPhone開發(fā)之深入淺出 (3) — ARC之前世今生中的描述。

3. 關(guān)于這一點(diǎn),,可以參考iPhone開發(fā)之深入淺出 (1) — ARC是什么 一文,,明白為什么 __unsafe_unretained 是危險(xiǎn)的。

 

 

from http://www./development-of-the-iphone-simply-7/


讓我們一個(gè)一個(gè)來分析

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多