過渡到ARC說明

ARC是一個編譯器特征,它提供了對OC對象自動管理內(nèi)存。ARC讓開發(fā)者專注于感興趣的代碼和對象的關(guān)系催训,而不用考慮對象的retain和release。

概要

ARC在編譯時期添加代碼宗收,保證對象可用漫拭。概念上說,ARC遵循手動引用計(jì)數(shù)的規(guī)則混稽,替開發(fā)者采驻,在編譯時期添加合適的代碼。

為了讓編譯器生成正確的代碼匈勋,ARC限制使用某些方法和使用toll-free橋接礼旅。ARC為對象引用和聲明的屬性引入了新的生命周期描述符。

Xcode4.2(Mac OS 10.6洽洁、10.7和iOS4和iOS5)支持ARC痘系,弱引用在10.6和iOS4上不支持。

Xcode提供了一個工具:自動機(jī)械得轉(zhuǎn)化為ARC(比如移除retain和release的調(diào)用)饿自,并幫助開發(fā)者解決不能自動遷移的問題汰翠。遷移工具將所有文件轉(zhuǎn)化成ARC,開發(fā)者也可以對單個文件實(shí)施ARC昭雌,方便于開發(fā)者對某些文件手動引用計(jì)數(shù)复唤。

ARC概要

ARC評估了對象的生命周期,并自動插入合適的代碼在編譯時期烛卧,從而代替開發(fā)者不得不考慮何時需要retain佛纫、release和autorelease。編譯器替開發(fā)者总放,生成合適的dealloc方法雳旅。一般來說,當(dāng)開發(fā)者需要在手動引用計(jì)數(shù)和ARC配合使用時候间聊,使用傳統(tǒng)ARC的Cocoa命名慣例是很重要的攒盈。

一個正確的完整的Person類如下:

@interface Person : NSObject

@property NSString *firstName;

@property NSString *lastName;

@property NSNumber *yearOfBirth;

@property Person *spouse;

@end

@implementation Person

@end

對象的屬性默認(rèn)是strong;strong屬性在 “ARC Introduces New Lifetime Qualifiers.”有描述

1 - (void)contrived {

3 ? ? Person *aPerson = [[Person alloc] init];

5 ? ? [aPerson setFirstName:@"William"];

7 ? ? [aPerson setLastName:@"Dudney"];

9 ? ? [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];

11 ? ? NSLog(@"aPerson: %@", aPerson);

13 ? ?}

ARC掌管了內(nèi)存管理哎榴,所以Person和NSNumber不會泄露型豁。

開發(fā)者還可以安全得實(shí)現(xiàn)Person類的方法takeLastNameFrom:

- (void)takeLastNameFrom:(Person *)person {

NSString *oldLastname = [self lastName];

[self setLastName:[person lastName]];

NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);

}

ARC確保oldLastName在NSLog之前不會被銷毀僵蛛。

ARC執(zhí)行了新的規(guī)則

ARC執(zhí)行了一些新的規(guī)則,是其他編譯模式?jīng)]有的迎变。這個規(guī)則是:致力于提供一個安全可靠的內(nèi)存管理模式充尉。在某些情況下,他們只是執(zhí)行最佳實(shí)踐衣形;某些情況驼侠,他們簡化你的代碼或者處理那沒明顯的不需要內(nèi)存問題。如果你違反這些規(guī)則谆吴,立即得到一個編譯錯誤倒源,而不會在運(yùn)行顯示一個微妙的bug。

●?開發(fā)者不能顯式調(diào)用dealloc句狼;不能實(shí)現(xiàn)和調(diào)用retain笋熬、release、retainCount和autorelease腻菇。

禁止使用@selector(retain),@selector(release)等等胳螟。

開發(fā)者仍可以實(shí)現(xiàn)dealloc方法,如果你想管理資源而不是變量筹吐。開發(fā)者不能release變量糖耸,但是可以調(diào)用[systemClassInstance? ? ? ? ? setDelegate:nil]在系統(tǒng)類上,或者其他不是用ARC編譯的代碼上丘薛。

ARC中自定義的dealloc方法嘉竟,不需要調(diào)用[super dealloc](其實(shí)這樣做就會導(dǎo)致編譯錯誤),編譯器會強(qiáng)制自動鏈接到父類榔袋。

開發(fā)者仍可以對Core Foundation-style對象周拐,使用CFRetain,CFRelease和其他相關(guān)方法。

● 不能使用NSAllocateObject或者NSDeallocateObject凰兑。開發(fā)者創(chuàng)建對象使用alloc妥粟,運(yùn)行時環(huán)境負(fù)責(zé)銷毀對象。

● 在C數(shù)據(jù)結(jié)構(gòu)中吏够,不能使用對象指針勾给。可以使用OC類來代替C的struct

● id和void*沒有自動轉(zhuǎn)換.

開發(fā)者必須使用特殊的類型轉(zhuǎn)化锅知。開發(fā)者需要通過函數(shù)參數(shù)傳遞播急,在OC對象和Core Foundation之間做類型轉(zhuǎn)換。

● 開發(fā)者不能使用NSAutoreleasePool對象售睹。ARC下使用@autoreleasepool桩警,它比NSAtuoreleasePool更有效率。

● 開發(fā)者不能使用內(nèi)存zones昌妹。不用再使用NSZone了捶枢。他們已經(jīng)被現(xiàn)代的OC運(yùn)行環(huán)境給忽略了握截。

為了配合手動引用計(jì)數(shù),ARC的方法命名有限制:

● 訪問器方法不能已new開頭烂叔,反過來就是:開發(fā)者不能聲明一個已new開頭的屬性谨胞,除非你給你指定一個getter方法

1 // Won't work:

2 @property NSString *newTitle;

3

4 // Works:

5 @property (getter=theNewTitle) NSString *newTitle;

6

ARC引入了新的Lifetime修飾符

ARC引入幾個新的修飾符和弱(weak)引用。弱引用不會延伸到對象生命周期蒜鸡,并自動設(shè)置為nil胯努,當(dāng)該對象沒有任何的強(qiáng)引用的時候。

開發(fā)者需要使用這些修飾來管理對象圖逢防。通常ARC不對循環(huán)引用做警告叶沛。謹(jǐn)慎的使用弱引用可以保證不會循環(huán)引用。

Property屬性

weak和strong關(guān)鍵字作為新的property屬性被引入胞四,例如:

1

2 @property(strong)?MyClass?*myObject;

3

4

5 //?except?that?if?the?MyClass?instance?is?deallocated,

6

7 @property(weak)?MyClass?*myObject;

ARC下恬汁,strong是默認(rèn)property屬性

變量的修飾符

開發(fā)者使用下面得lifetime描述符伶椿。

__strong

__weak

__unsafe_unretained

__autoreleasing

● 默認(rèn)是__strong辜伟。只要對象還有強(qiáng)引用,該對象“活著”脊另。

● __weak不保留對象导狡,只是簡單引用。weak對象將被設(shè)置nil偎痛,當(dāng)對象沒有任何強(qiáng)引用的時候旱捧。

● __unsafe_unretained 不保留對象,只是簡單引用踩麦。但是不設(shè)置為nil枚赡,當(dāng)對象沒有任何強(qiáng)引用得時候。如果對象被銷毀谓谦,? __unsafe_unretained的對象將會野指針贫橙。

● __autoreleasing 用于標(biāo)識id*的引用參數(shù),或者需要自動釋放的返回的對象反粥。

開發(fā)者需要正確修飾變量卢肃。使用下面的格式來修飾變量聲明。

類名* ?修飾 ?變量名 (ClassName * qualifier variableName;)

例如:

1 MyClass?*?__weak?myWeakReference;

2 MyClass?*?__unsafe_unretained?myUnsafeReference;

其他的變種在技術(shù)上是不正確的才顿,但可能可以通過編譯莫湘。了解更多http://cdecl.org/

在棧上小心使用__weak≈F考慮下面的代碼:

1 NSString?*?__weak?string?=?[[NSString?alloc]?initWithFormat:@ "First?Name:?%@" ,?[self?firstName]];

2 NSLog(@ "string:?%@" ,?string);

盡管string在初始化后被使用了幅垮。但是,由于在賦值的時候沒有強(qiáng)引用尾组;因此它將立即被銷毀忙芒。

開發(fā)者同樣需要注意傳遞引用的地方巩螃,例如下面的代碼:

1 NSError?*error;

2 BOOL?OK?=?[myObject?performOperationWithError:&error];

3 if ?(!OK)?{

4 ???? //?Report?the?error.

5 ???? //?...

然而,這種錯誤是隱含的匕争。

1 NSError?*?__strong?e;

并且聲明的方法可能是下面這樣:

1 -(BOOL)performOperationWithError:(NSError?*?__autoreleasing?*)error;

編譯器將重寫代碼:

1 NSError?*?__strong?error;

2 NSError?*?__autoreleasing?tmp?=?error;

3 BOOL?OK?=?[myObject?performOperationWithError:&tmp];

4 error?=?tmp;

5 if ?(!OK)?{

6 ???? //?Report?the?error.

7 ???? //?...

本地變量聲明(__strong)和參數(shù)(__autoreleasing)導(dǎo)致編譯器創(chuàng)建臨時變量避乏。當(dāng)開發(fā)者對__strong對象取地址,將參數(shù)聲明為id __strong*甘桑,就得到原始的指針拍皮。或者開發(fā)者可以將變量聲明為__autoreleasing

使用Lifetime修飾符跑杭,避免循環(huán)引用

開發(fā)者可以通過lifetime修飾符來避免循環(huán)引用铆帽。例如,如果你有一個對象圖(關(guān)于父-子繼承)德谅。并且父類需要引用子類爹橱,相反子類也要用。這時候窄做,開發(fā)者把parent-to-child寫做strong并把child-to-parent關(guān)系寫作weak愧驱。其他情況可能有些麻煩,特別是調(diào)用block變量的時候椭盏。

手動引用計(jì)數(shù)模式下组砚,__block id x 這樣的寫法,不會對x進(jìn)行retain掏颊。在ARC模式糟红,__block id x;默認(rèn)retain x(就像其他變量一樣)。如果想在ARC模式下乌叶,得到手動引用計(jì)數(shù)的效果盆偿,開發(fā)者可以使用__unsafe_unretained __block id x。顧名思義准浴,__unsafe_unretained __block id x是危險(xiǎn)的(因?yàn)樗赡軐?dǎo)致野指針)因此也不建議使用事扭。好的解決方案是:使用__weak或者將__block的值設(shè)置為nil,來打斷retain循環(huán)兄裂。

下面的代碼段展示了如何使用手動引用計(jì)數(shù)

MyViewController *myController = [[MyViewController alloc] init…];

// ...

myController.completionHandler =? ^(NSInteger result) {

[myController dismissViewControllerAnimated:YES completion:nil];

};

[self presentViewController:myController animated:YES completion:^{

[myController release];

}];

正如說的那樣句旱,開發(fā)者可以使用__block修飾符并且設(shè)置myController變量為nil,在完成處理的時候晰奖。

1 MyViewController * __block myController = [[MyViewController alloc] init…];

2 // ...

3 myController.completionHandler =? ^(NSInteger result) {

4 ? ? [myController dismissViewControllerAnimated:YES completion:nil];

5 ? ? myController = nil;

6 };

或者谈撒,你可以使用臨時的__weak變量。下面是一個簡單的實(shí)現(xiàn)

1 MyViewController *myController = [[MyViewController alloc] init…];

2 // ..

3 MyViewController * __weak weakMyViewController = myController;

4 myController.completionHandler =? ^(NSInteger result) {

1 ? ? [weakMyViewController dismissViewControllerAnimated:YES completion:nil];

1 };

1 ? 對于non-trivial循環(huán)匾南,開發(fā)者應(yīng)該使用下面代碼:

MyViewController *myController = [[MyViewController alloc] init…];

// ...

MyViewController * __weak weakMyController = myController;

myController.completionHandler =? ^(NSInteger result) {

MyViewController *strongMyController = weakMyController;

if (strongMyController) {

// ...

[strongMyController dismissViewControllerAnimated:YES completion:nil];

// ...

}

else {

// Probably nothing...

}

};

在某些情況啃匿,開發(fā)者使用__unsafe_unretained,如果類本身不是__weak修飾。然而溯乒,這樣將變得不切合實(shí)際了夹厌,因?yàn)樗赡芎茈y或者不可能去驗(yàn)證:__unsafe_unretained的指針仍然可用并且指向某些變量。

ARC使用一個新語句管理Autorelease Pools

使用ARC裆悄,開發(fā)者不能直接使用NSAutoreleasePool來管理autorelease pools矛纹。而使用@autoreleasepool代替它。

@autoreleasepool {

// Code, such as a loop that creates a large number of temporary objects.

}

這個簡單的結(jié)構(gòu)允許編譯器思考引用計(jì)數(shù)的狀態(tài)光稼。進(jìn)入的時候或南,自動釋放池被push。在正常退出的時候自動釋放池配poped出來艾君。為了配合現(xiàn)有代碼采够,如果代碼異常退出,自動釋放池將不會pop出來冰垄。它比NSAutoreleasePool更有效率蹬癌;因此建議開發(fā)者替換NSAtuoreleasePool。

管理Outlet的模式在各個平臺變得一致

在iOS和OS X聲明Outlet的模式在ARC中發(fā)生改變虹茶,并且在兩個平臺上變的一致逝薪,你應(yīng)該采用的模式是:outlet修飾符應(yīng)該是weak,除了那些從File’s owner到nib文件( 或者storyBoard場景)的高級對象写烤,他們應(yīng)該是強(qiáng)引用翼闽。

棧變量被初始化為nil

使用ARC拾徙,strong洲炊、weak和autoreleasing棧變量將會隱式的初始化為nil,例如:

- (void)myMethod {

NSString *name;

NSLog(@"name: %@", name);

}

將打印出null尼啡,而不是崩潰暂衡。

使用編譯器選項(xiàng)來開啟和關(guān)閉ARC

開發(fā)者使用-fobjc-arc 編譯選項(xiàng)開啟ARC,還可以對某一個文件使用ARC崖瞭,便于在使用手動引用計(jì)數(shù)的文件中使用ARC狂巢。對于已經(jīng)使用ARC的工程,仍可以指定一個文件來關(guān)閉ARC通過-fno-objc-arc編譯選項(xiàng)书聚。

管理Toll-Free Bridging

在多數(shù)的Cocoa程序中唧领,開發(fā)者需要使用Core Foundaton-style對象,無論是從Core Foundation框架還是從Core foundation的其他框架比如Core Graphics雌续。

編譯器不會自動管理Core foundation對象的生命周期斩个。開發(fā)者必須根據(jù)COreFoundation的內(nèi)存管理規(guī)則,使用CFRetain和CFRelease驯杜。

如果開發(fā)者在OC和Core foundation兩種對象做轉(zhuǎn)換受啥,需要告訴編譯器對象的所有權(quán)。

* __bridge: 只做類型轉(zhuǎn)化,不修改相關(guān)對象的引用計(jì)數(shù)滚局,原來的Core Foundation對象在不用時居暖,需要調(diào)用CFRelease方法

* __bridge_retained(CFBridgingRetain): 類型轉(zhuǎn)化后,將相關(guān)對象的引用計(jì)數(shù)+1藤肢,原來的Core Foundation對象在不用時太闺,需要調(diào)用CFRelease方法。

* __bridge_transfer: 類型轉(zhuǎn)換后嘁圈,將該對象的引用計(jì)數(shù)交給ARC管理跟束,Core Foundation對象在不用時,不在需要調(diào)用CFRelease方法丑孩。

例如冀宴,現(xiàn)有代碼:

- (void)logFirstNameOfPerson:(ABRecordRef)person {

NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);

NSLog(@"Person's first name: %@", name);

[name release];

}

開發(fā)用下面的代碼代替

1 - (void)logFirstNameOfPerson:(ABRecordRef)person {

2

3 ? ? NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));

3 ? ? NSLog(@"Person's first name: %@", name);

1 }

2

編譯器處理從COcoa方法返回的 CF 對象

編譯器知道返回Core foundaion類的OC的方法,遵循歷史的規(guī)定温学。例如略贮,編譯器知道從UIColor的CGColor方法返回的GCColor是不擁有的。開發(fā)者必須使用合適的類型去轉(zhuǎn)化仗岖。例如:

NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];

[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];

使用所有權(quán)關(guān)鍵字轉(zhuǎn)化函數(shù)參數(shù)

當(dāng)開發(fā)者在OC和Core foundation的對象之間轉(zhuǎn)化時逃延,需要告訴編譯器傳遞object的所有權(quán)。Core foundation對象所有權(quán)的規(guī)則在CoreFoundation的內(nèi)存管理規(guī)則中轧拄。OC的所有權(quán)規(guī)則在Advanced Memory Management Programming Guide中揽祥。

下面的代碼段,數(shù)組傳遞給CGGradientCreateWithCorlors函數(shù)需要一個合適的轉(zhuǎn)化檩电。數(shù)組是arrayWithObjects返回的拄丰,所以,不要將所有權(quán)傳遞給函數(shù)俐末,因此使用__bridge

NSArray *colors = <#An array of colors#>;

CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

下面代碼段實(shí)現(xiàn)了一個context料按,使用Core Foundation內(nèi)存管理的方法。

1 - (void)drawRect:(CGRect)rect {

1 ? ? CGContextRef ctx = UIGraphicsGetCurrentContext();

2 ? ? CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

7 ? ? CGFloat locations[2] = {0.0, 1.0};

1 ? ? NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];

2 ? ? [colors addObject:(id)[[UIColor lightGrayColor] CGColor]];

2 ? ? CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

4 ? ? CGColorSpaceRelease(colorSpace);? // Release owned Core Foundation object.

6 ? ? CGPoint startPoint = CGPointMake(0.0, 0.0);

1 ? ? CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));

2 ? ? CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint,

1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);

3 ? ? CGGradientRelease(gradient);? // Release owned Core Foundation object.

5 }

將工程轉(zhuǎn)化為ARC卓箫,遇到的常見問題

當(dāng)遷移現(xiàn)有的項(xiàng)目载矿,你可能會遇到的各種問題。這里有一些共同的問題烹卒,共同解決方案闷盔。

● 不能調(diào)用retain,release或者autorelease旅急,這是一種特性逢勾,甚至不可以這么寫:

? while ([x retainCount]) { [x release]; }

● 不能調(diào)用dealloc

通常,開發(fā)者在單例的實(shí)現(xiàn)或者替換一個對象的init方法的時候調(diào)用dealloc坠非。對于單例模式敏沉,使用共享實(shí)例模式。在init方法中,你不用調(diào)用dealloc盟迟,因?yàn)閷ο髸会尫徘镉荆?dāng)重寫self的時候。

● 不能使用NSAutoreleasePool對象

表格@autoreleasepool{}代替NSAutoreleasePool.這將強(qiáng)制一個block處于一個自動釋放池中攒菠。它比NSAutoreleaePool快6倍迫皱。@autoreleasepool也在在非ARC模式下工作。

● ARC需要開發(fā)者對[super init]賦值給self在init方法中辖众。

下面代碼是不可行的

1 [super init];

簡單的修正是:

self = [super init];

最合適的修復(fù)是這樣的卓起,在初始化之前先檢測結(jié)果是不是nil。

? self = [super init];

? if (self) {

? ? ...

● 不能實(shí)現(xiàn)retain和release方法凹炸。

實(shí)現(xiàn)自定義的retain和release方法打破弱指針戏阅。提供了幾個常用的 “實(shí)現(xiàn)自定義”的原因。

1.性能

不要這么做啤它,NSObject的retain和release已經(jīng)很快了奕筐。如果你發(fā)現(xiàn)仍有問題,請?zhí)岢鲞@個bug

2.實(shí)現(xiàn)一個自定義的弱指針系統(tǒng)

使用__weak代替

3.實(shí)現(xiàn)單例

使用shared instance pattern代替变骡±牒眨或者使用類來代替方法,避免分配對象塌碌。

● assigned 將變成strong

在ARC之前渊胸,變量的assigned的不會延伸到對象的生命周期。為了讓property變成強(qiáng)引用台妆,開發(fā)者通常實(shí)例化或者synthesized訪問器方法翎猛,里面是內(nèi)存管理方法。相比之下频丘,你可以這樣實(shí)現(xiàn)訪問器方法:

1 @interface MyClass : Superclass {

2 ? ? id thing; // Weak reference.

1 }

3 // ...

1 @end

1 @implementation MyClass

3 - (id)thing {

1 ? ? return thing;

2 }

3

4 - (void)setThing:(id)newThing {

5 ? ? thing = newThing;

1 }

9 // ...

1 @end

1 ARC下办成,實(shí)例中的變量默認(rèn)是strong引用,assigning一個對象給實(shí)例中的變量延伸到對象的生命周期搂漠。遷移工具不能決定一個實(shí)例變量即將weak。保持相同的行為之前某弦,你必須標(biāo)記實(shí)例變量是weak桐汤,或聲明它的property

1 @interface MyClass : Superclass {

2

3 ? ? id __weak thing;

4

5 }

6

7 // ...

8

9 @end

10

1

2 @implementation MyClass

3

4 - (id)thing {

5

6 ? ? return thing;

7

8 }

9

10 - (void)setThing:(id)newThing {

11

12 ? ? thing = newThing;

13

14 }

15

16 // ...

17

18 @end

19

或者

1 @interface MyClass : Superclass

2 @property (weak) id thing;

3 // ...

4 @end

5

6 @implementation MyClass

7 @synthesize thing;

8 // ...

9 @end

10

● 不能使用strong ids在c的數(shù)據(jù)結(jié)構(gòu)

例如,下面的c結(jié)構(gòu)將不能編譯過

1 struct X { id x; float y; };

這是因?yàn)閤默認(rèn)是strong retain靶壮,但是怔毛,在正常運(yùn)行情況下,編譯器不能安全的合成所有需要的代碼腾降。比如:如果你傳遞一個指針給x或者y后拣度,執(zhí)行了free,每一個id將被release掉,在struct被free之前抗果。編譯器不能可靠的做這些筋帖。所以strong ids在結(jié)構(gòu),在ARC中完全不允許冤馏。下面是一些解決方案:

1.用OC類代替c結(jié)構(gòu)日麸。這應(yīng)該是最好的解決辦法。

2.如果使用OC類是次要的方法(可能你想要一個高密度的結(jié)構(gòu)數(shù)組)逮光,那么考慮使用void*代替代箭。這需要使用顯示的轉(zhuǎn)化。

3.把對象引用作為__unsafe_unretained涕刚。這種方法是半常見的模式嗡综,這樣是有用的。

struct x { NSString *S;? int X; } StaticArray[] = {

@"foo", 42,

@"bar, 97,

...

};

開發(fā)者這樣聲明

1 struct x { NSString * __unsafe_unretained S; int X; }

這可能是有問題的杜漠,如果對象可以被釋放時指針是不安全的蛤高,但它是非常有用的東西,被稱為是字符串常量碑幅。

● 不能直接將id和void*進(jìn)行轉(zhuǎn)化(包含Core Foundation類型)參考Managing Toll-Free Bridging

經(jīng)常遇到的問題

我該怎樣認(rèn)識ARC戴陡?它在哪兒放置retains/releases。

不要想什么地方調(diào)用retain/release沟涨,考慮程序本身算法吧恤批。考慮"strong and weak"關(guān)系裹赴,對象的所有權(quán)關(guān)系和可能存在的循環(huán)引用喜庞。

我還需要寫dealloc方法么

可能需要。因?yàn)锳RC不會自動對 Core Foundation 對象棋返,文件描述符等等進(jìn)行malloc/free延都,,這些資源扔需要寫dealloc方法睛竣。

不能release對象的變量晰房,但是可以調(diào)用[self setDelegate:nil]在系統(tǒng)的類和其他不用ARC的代碼。

ARC種 不需要dealloc方法射沟,或者[super dealloc]殊者;在運(yùn)行時系統(tǒng)調(diào)用super代碼。

在ARC種验夯,仍存在循環(huán)引用猖吴?

是的。ARC自動retain/release并可能繼承了循環(huán)引用的問題挥转。幸運(yùn)的是:遷移到ARC的代碼很少泄露海蔽,因?yàn)闊o論properties是不是retain的共屈,都被被聲明為retain了。

在ARC種blocks是如何工作的

Block能正常工作党窜,當(dāng)你在棧上傳遞的時候拗引,比如作為返回值。你無需block copy了刑然。當(dāng)你傳遞block在棧下面的時候寺擂,添加到arrayWithObjects等需要retain的地方,需要使用[^{ }copy]泼掠。

有一件事情需要清除:NSString *__block myString是retain在ARC模式種怔软,不可能是野指針。為了得到以前的行為择镇,使用__block NSString *__unsafe_unretained myString 或者使用__block NSString *__weak myString.

我可以在雪豹OS種開發(fā)中使用ARC么挡逼?

不行。雪豹版本的Xcode4.2不支持ARC腻豌。

ARC下家坎,可以創(chuàng)建C語言的retain的指針數(shù)組么

可以

1 // Note calloc() to get zero-filled memory.

2

3 __strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(entries, sizeof(SomeClass *));

4

5 for (int i = 0; i < entries; i++) {

6

7 ? ? dynamicArray[i] = [[SomeClass alloc] init];

8

9 }

10

11

12

13 // When you're done, set each entry to nil to tell ARC to release the object.

14

15 for (int i = 0; i < entries; i++) {

16

17 ? ? dynamicArray[i] = nil;

18

19 }

20

21 free(dynamicArray);

22

下面是一些注意的地方:

● 你要寫__strong SomeClass **在某些情況,默認(rèn)情況是__autoreleasing SomeClass **.

● 開辟的內(nèi)存必須是零填充

● 需要設(shè)置每一項(xiàng)為nil在釋放array的時候(memset和bzero不好使的)

ARC慢么吝梅?

取決于你怎么測量虱疏,通常是不慢。編譯器消除很多無關(guān)緊要的retain/release調(diào)用苏携。投入很大的努力在加快OC下的運(yùn)行環(huán)境做瞪。尤其是返回一個retian/autoreleased對象,ARC并不是真正將它放到自動釋放池右冻。

有一件事需要清除:優(yōu)化器不在debug模式下装蓬。所以想看到更多的retain/release的調(diào)用,使用-O0比-Os

ARC在ObjC++模式下工作么纱扭?

是的牍帚,甚至可以將strong/weakids在類和容器中。ARC編譯器合成retain/release邏輯在拷貝構(gòu)造函數(shù)和析構(gòu)函數(shù)鐘乳蛾。

哪些類不支持weak引用暗赶?

下面的類不能創(chuàng)建弱引用:

NSATSTypesetter, NSColorSpace, NSFont, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, and NSTextView.

對于聲明properties時,你應(yīng)該使用retain代替weak屡久。對于變量你應(yīng)該使用__unsafe_unretained代替__weak.另外忆首,你不能創(chuàng)建這些類的弱引用:NSHashTable, NSMapTable, or NSPointerArray

對NSCell和其他類使用NSCopyObject時候。

沒什么特別的被环。ARC負(fù)責(zé)的顯示retain的場景。ARC模式下详幽,所有的copy方法應(yīng)該僅僅copy實(shí)例變量筛欢。

我可以對某個文件不使用ARC么浸锨?

是的。當(dāng)開發(fā)者遷移工程到ARC時版姑,對所有OC源文件設(shè)置為-fobjc-arc編譯選項(xiàng)柱搜。開發(fā)者可以指定一個文件設(shè)置-fno-objc-arc編譯選項(xiàng)。

GC(Grabage Collection)在mac上過時了?

Grabage Collection在10.8上已經(jīng)過時剥险,將來會重OS X中移除聪蘸。ARC將是收推薦的替代技術(shù)。為了幫助遷移現(xiàn)有程序表制,ARC遷移工具在Xcode >=4.3 支持將GC遷移到ARC健爬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市么介,隨后出現(xiàn)的幾起案子谷徙,更是在濱河造成了極大的恐慌龟梦,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異甲捏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谆扎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門霉撵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帘撰,你說我怎么就攤上這事跑慕。” “怎么了骡和?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵相赁,是天一觀的道長。 經(jīng)常有香客問我慰于,道長钮科,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任婆赠,我火速辦了婚禮绵脯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘休里。我一直安慰自己蛆挫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布妙黍。 她就那樣靜靜地躺著悴侵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拭嫁。 梳的紋絲不亂的頭發(fā)上可免,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天抓于,我揣著相機(jī)與錄音,去河邊找鬼浇借。 笑死捉撮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妇垢。 我是一名探鬼主播巾遭,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闯估!你這毒婦竟也來了灼舍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤睬愤,失蹤者是張志新(化名)和其女友劉穎片仿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尤辱,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砂豌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了光督。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阳距。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖结借,靈堂內(nèi)的尸體忽然破棺而出筐摘,到底是詐尸還是另有隱情,我是刑警寧澤船老,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布咖熟,位于F島的核電站,受9級特大地震影響柳畔,放射性物質(zhì)發(fā)生泄漏馍管。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一薪韩、第九天 我趴在偏房一處隱蔽的房頂上張望确沸。 院中可真熱鬧,春花似錦俘陷、人聲如沸罗捎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桨菜。三九已至,卻和暖如春捉偏,著一層夾襖步出監(jiān)牢的瞬間雷激,已是汗流浹背替蔬。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工告私, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屎暇,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓驻粟,卻偏偏與公主長得像根悼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蜀撑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

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