您的位置:首页 > 其它

iphone 自动引用计数(ARC)

2012-10-12 13:51 337 查看
Transitioning to ARC Release Notes

自动引用计数(ARC),是一项为Objective - C程序在编译时提供自动内存管理的功能。ARC可以让你把注意力集中在你感兴趣的代码,对象图,和你的应用程序中的对象之间的关系,让你不必再花费精力在retain和release操作上。正如下图所示,ARC可以减少开发中的内存管理步骤,简化开发。


Contents:

Summary

ARC
Overview

Managing
Toll-Free Bridging

Common
Issues While Converting a Project

Frequently
Asked Questions

概要

ARC工作方式是在代码编译的时候,自动加入内存控制代码,来控制对象的生命周期,确保对象使用的内存空间正确的分配和释放。从概念上来说,ARC遵循Advanced
Memory Management Programming Guide的手动内存使用守则,通过加入retain,release,autorelease 方法,确保实现与你手动管理内存一样的效果。

为了代码能正常编译,ARC对toll-free bridging(详见“Toll-Free
Bridged Types”)使用的方式、方法进行了限制,同时ARC还为对象和声明的属性引入了新的生命周期。

ARC支持Mac OS X v10.6/10.7 (64-bit applications) 上的Xcode 4.2,支持iOS4、iOS5。但是ARC在Mac OS X v10.6和iOS4上,不支持Weak references。

Xcode中加入了一个新的工具,用于自动处理ARC里机械式的操作,如移出项目代码中的retain和release方法 调用),而且它还可以帮你修订那些不能自动移植的代码。这个代码移植工具,支持转化项目中的所有代码为ARC模式,如果觉得不方便,你也可以选择手动方式来处理这些文件。

参考资料:

Advanced
Memory Management Programming Guide

Memory
Management Programming Guide for Core Foundation

ARC概述

ARC可以代替你去记住何时应该retain,何时应该release,何时要autorelease;ARC回为你评估你的项目所需的生命周期,并且自动地在编译时为你调用适当的方法。编译器还可以帮你生成dealloc方法。一般来说,如果你只使用ARC,当你需要使用手动引用计数的代码互操作的时候,常规Cocoa命名规约是重要的。

一个完整、正确的,用来描述“Person”特性的类的实现(implementation),是这样的:

复制代码

@interface Person : NSObject@property (nonatomic, strong) NSString *firstName;@property (nonatomic, strong) NSString *lastName;@property (nonatomic, strong) NSNumber *yearOfBirth;@property (nonatomic, strong) Person *spouse;@end @implementation Person@synthesize
firstName, lastName, yearOfBirth, spouse;@end

( strong 属性的描述参见 “ARC
Introduces New Lifetime Qualifiers”.)

使用ARC的话,你可以实现一个人为的方法,如下:

复制代码

- (void)contrived { Person *aPerson = [[Person alloc] init]; [aPerson setFirstName:@"William"]; [aPerson setLastName:@"Dudney"]; [aPerson:setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]]; NSLog(@"aPerson: %@", aPerson);}

因为使用ARC来管理内存,所以无论是“Person”或者“NSNumber”都不会发生内存泄漏。

你也可以像这样更安全的执行“Person”的“takeLastNameFrom: ”方法:

复制代码

- (void)takeLastNameFrom:(Person *)person { NSString *oldLastname = [self lastName]; [self setLastName:[person lastName]]; NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);}

ARC在NSLog方法调用之前是不会释放oldLastName的。

使用ARC必须遵守的新规则

为了正常运行,ARC引入了一些特有的新规则。新规则的用于提供一个完整可靠的内存管理模式;这些规则有些是用于更好的用户体验,另外一些则是用于简化你的编码,或让你不必再为内存管理操心。如果你违反了这些规则,在你编译的时候就会报错了,而不是当你编译成功,开始运行时出现一些bug。

不可以再显示调用dealloc、或实现调用retain、release、retainCount、autorelease这些方法。

很明显也不能使用@selector(retain), @selector(release),等等。

当你需要管理一些非实例变量的资源时,你可以实现一个dealloc方法。你不需要也不能去释放实例变量,但您可以调用[systemClassInstance setDelegate:nil]或不使用ARC编译的内存管理代码。

在ARC下去自定义dealloc方法不需要调用 [super dealloc],(实际上如果你调用了 [super dealloc],编译器会报错)。super的调用是由编译器自动强制执行的。

CFRetain, CFRelease, 还有其他Core Foundation-style objects函数 (详见“Managing Toll-Free Bridging”)还是可以执行的。

不能使用NSAllocateObject或NSDeallocateObject。

使用alloc来创建对象,由ARC来管理对象运行时的释放。

不能在C语言的结构体中使用对象指针。

建议使用Objective-C的class来管理数据格式,来代替C语言的struct。

不能隐式转换 id和void *。

你必须告诉编译器转换的类型。当你需要在obj-C的对象和Core Foundation 类型之间转换时,你可以通过函数的参数来做。详见“Managing Toll-Free Bridging”。

不能使用NSAutoreleasePool对象。

ARC提供了一个@autoreleasepool块来代替,这个块相比NSAutoreleasePool来说,具有更高的有效性。

不能使用memory Zone。

因为现在Objective-C运行时已经忽略NSZone了,所以没必要再使用NSZone了。

为了可以和手动内存管理(manual retain-release)的代码兼容,ARC提出了一些变量方法的命名规约。

你不能用“new”来做property的名字开头。

ARC引入的新的生命周期修饰符

ARC引入了一些新的生命周期修饰符和zeroing weak引用.。一个weak引用不会改变它所指向对象的生命周期。 一个zeroing weak引用会在它指向的对象被释放以后,自动赋为nil。

在你的程序中,你应该灵活运用修饰符来管理你的对象图。特别是,ARC不会去保护strong引用的retain周期(详见“Practical
Memory Management”),所以谨慎使用weak可以确保你不会创建循环引用。

Property 属性

在下面的几个例子中,我们介绍一下新的property属性关键词weak、strong。

复制代码

// 下面的声明和: @property(retain) MyClass *myObject;是一样的@property(strong) MyClass *myObject; // 下面的声明和 "@property(assign) MyClass *myObject;"是相似的,// 但是,当 MyClass 被释放的时候,值被设为nil,而不是一个野指针 @property(weak) MyClass *myObject;

变量修饰符

你可以用下面的生命周期修饰符来声明变量,就像你使用const一样

__strong
__weak
__unsafe_unretained
__autoreleasing
__strong是默认的修饰符。 __weak修饰了一个自动nil的weak引用。__unsafe_unretained声明了一个不会自动nil的weak引用。当变量被释放,那么它就变成了一个野指针了。__autoreleasing 用来修饰一个声明为 (id *)的函数的参数,当函数返回值时被释放。

当你用__weak来修饰栈上的变量时,你必须格外小心。参考下面的例子:

复制代码

NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];NSLog(@"string: %@", string);

虽然string在分配空间并初始化后就被赋值,但是没有别的strong引用对象指向string,所以string被立刻释放了。很明显,NSLog显示出的string值是nil、

同样,你需要在对象值传递时格外注意。下面的代码是可以执行的:

复制代码

NSError *error = nil;BOOL OK = [myObject performOperationWithError:&error];if (!OK) { // Report the error. // ...

However, the error declaration is implicitly:但是,error的声明是隐式的:

NSError * __strong e = nil;
而函数声明是这样的:

-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
那么,编译器会重写代码,变成:

复制代码

NSError __strong *error = nil;NSError __autoreleasing *tmp = error;BOOL OK = [myObject performOperationWithError:&tmp];error = tmp;if (!OK) { // Report the error. // ...

当本地变量声明(__strong *error)和函数的参数((NSError * __autoreleasing *)error)不匹配的时候,编译器会创建一个临时变量。当你获得一个__strong变量的地址时,你可以初始化一个id __strong *的指针来声明 ,这样你就可以获得指针的原型,或者你可以声明一个变量为__autoreleasing。

使用生命周期修饰符来避免Strong引用周期

你可以使用生命周期修饰符来避免Strong引用周期。例如,当你制作了一组父子结构的对象,而且父类要引用子类,则会出现Strong引用周期;反之,当你将一个父类指向子类为strong引用,子类指向父类为weak引用,就可以避免出现Strong引用周期。当对象包含block objects时,这样的情况会变的更加隐性。

在手动内存管理模式下, __block id x; 控制x内存计数增加。 在ARC模式下,__block id x默认对x内存技术增加。为了使手动内存管理模式代码可以在ARC模式下正常工作, 你可以用__unsafe_unretained来修饰__block id x;。就和“__unsafe_unretained”字面上的意思一样,;然而,这样一个non-retained变量是危险的(因为它会变成一个野指针) 会带来不良后果。有两种更好一点的方法来处理,一是使用__weak (当你不需要支持iOS 4或OS
X v10.6), 二是设__block值为nil,结束他的生命周期。

下面是手动内存管理的代码,说明了这个问题,

复制代码

MyViewController *myController = [[MyViewController alloc] init…];// ...myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil];};[self presentViewController:myController animated:YES completion:^{
[myController release];}];

如上所述,相反,你可以使用 __block修饰符然后设置myController的值为nil:

复制代码

__block MyViewController *myController = [[MyViewController alloc] init…];// ...myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; myController = nil;};

另外,你还可以使用一个临时__weak变量。下面的例子下面的例子说明了一个简单的实现:

复制代码

MyViewController *myController = [[MyViewController alloc] init…];// ...__weak MyViewController *weakMyViewController = myController;myController.completionHandler = ^(NSInteger result) { [weakMyViewController dismissViewControllerAnimated:YES completion:nil];};

对于一般情况,你可以这样来做:

复制代码

MyViewController *myController = [[MyViewController alloc] init…];// ...__weak MyViewController *weakMyController = myController;myController.completionHandler = ^(NSInteger result) { MyViewController *strongMyController = weakMyController; if (strongMyController)
{ // ... [strongMyController dismissViewControllerAnimated:YES completion:nil]; // ... } else { // Probably nothing... }};

在某些情况下,比如类不支持__weak模式时,你可以使用__unsafe_unretained。但是,很难保证正确的生命周期,能难或者说不可能去验证一个__unsafe_unretained指针是否有效。

ARC提供一个新的声明来管理Autorelease Pools

使用ARC,你不能再使用NSAutoReleasePool类来直接管理autorelease pools。取而代之,ARC提供了一个新的Objective-C语法来代替。

复制代码

@autoreleasepool { // Code, such as a loop that creates a large number of temporary objects.}

通过上面的新语法,可以编译器管理autorelease pools的状态。

在这个@autoreleasepool入口,autorelease pool会压入栈中,当正常退出的时候(break, return, goto, fall-through等),autorelease pool 会出栈,但是当出口代码不兼容,异常退出autorelease pool,则autorelease pool 就不会出栈。

这个语法在所有的Objective-C模式下都能工作。它比NSAutoReleasePool更有效率。建议你把原先的所有NSAutoReleasePool代码都改成新的模式。

Patterns for Managing Outlets Become Consistent
Across Platforms

在被ARC处理过的iOS和OS X中,声明的outlets将会趋于统一。

一般来说outlets变量被修饰为weak,但是如果outlets变量的所有者是nib文件中的top-level对象(或者是storyboard scene)时,应被修饰为strong。

详细参考Resource
Programming Guide中的“Nib
Files”。

栈变量必须初始化为nil

使用ARC模式,strong,weak,autoreleasing栈变量都被隐式的初始化为nil,例如:

复制代码

- (void)myMethod { NSString *name; NSLog(@"name: %@", name);}

运行是程序不会崩溃,NSLog会打印出“null”。

使用编译标识来开关ARC模式

你可以使用 -fobjc-arc来启用ARC。你也可以使用-fno-objc-arc来为某个你希望使用手动管理内存的文件来禁用ARC。

Xcode4.2再MAC OS X10.6和10.7(64位应用)和iOS 4,iOS5支持ARC,Mac OS X 10.6和iOS4不支持weak引用,Xcode4.1以及以前的版本不支持ARC。

你也可以用在一个逐文件处理的方法中使用ARC来手动处理某些文件。For projects that employ ARC as the default approach, you can disable ARC for a specific file using a new-fno-objc-arc compiler flag for that file.

管理 Toll-Free Bridging

在许多的cocoa应用中,你需要用到Core Foundation类型,无论是来自Core Foundation framework本身 (例如CFArrayRefCFMutableDictionaryRef)或是由Core
Foundation扩展出的framework,例如Core Graphics (例如CGColorSpaceRefCGGradientRef).

编译器不会自动管理Core Foundation对象的生命周期;你必须使用CFRetainCFRelease (或相应的特殊类型的变量)
来符合Core Foundation内存管理规则 (详见Memory
Management Programming Guide for Core Foundation).

如果你在Objective-C和Core Foundation-style类型对象之间转换, 你需要用一个转换(定义在inobjc/runtime.h)或一个Core Foundation-style的宏(定义在NSObject.h),来告诉编译器这个对象的所属关系:

如果你倾向与用函数调用,你可以用宏例如CFBridgingRetain。这个宏使用新的方法将id和void* 之间转换,并告诉编译器关于这个void*的内存计数器的值。

复制代码

NS_INLINE CFTypeRef CFBridgingRetain(id X) { return (__bridge_retain CFTypeRef)X;} NS_INLINE id CFBridgingRelease(CFTypeRef X) { return (__bridge_transfer id)X;}

需要使用(__bridge)。

如果你喜欢C语言式样的转换,你可以直接使用转换:

复制代码

id my_id;CFStringRef my_cfref;...NSString *a = (__bridge NSString*)my_cfref; // Noop cast.CFStringRef b = (__bridge CFStringRef)my_id; // Noop cast....NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRefCFStringRef d = (__bridge_retained
CFStringRef)my_id; // returned CFRef is +1

编译器处理从CF Objects返回的Cocoa方法

编译器理解遵从Core Foundation返回的Cocoa命名转换Objective-C方法,(详见Advanced
Memory Management Programming Guide)。例如,编译器知道,在iOS里,CGColor返回的CGColor不属于UIColor。下面的方法来说明:

复制代码

- (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer]; gradientLayer.colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],
[[UIColor lightGrayColor] CGColor], nil]; gradientLayer.startPoint = CGPointMake(0.0, 0.0); gradientLayer.endPoint = CGPointMake(1.0, 1.0); } return self;}

转换函数的参数使用所属关系关键字

当你用转换Objective-C和Core Foundation对象类型的时候, 你需要去告诉编译器这个传入的参数的所属关系。Core Foundation对象的所属关系规则定义在Core Foundation memory management rules中(详见Memory
Management Programming Guide for Core Foundation);Objective-C对象规则定义在Advanced
Memory Management Programming Guide中。

下面所示代码中,传入CGGradientCreateWithColors函数的数组需要进行转换。所返回的对象从属关系arrayWithObjects: 没有被传入函数中,转换使用了关键字__bridge。

复制代码

NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor], [[UIColor lightGrayColor] CGColor], nil];CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

下面的代码演示了,注意所有核心内存管理函数都是遵循基础核心内存管理规则的:

复制代码

- (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGFloat locations[2] = {0.0, 1.0}; NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor]
CGColor], [[UIColor lightGrayColor] CGColor], nil]; 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.}

转换旧Project使用ARC时出现的共同问题

当你运行一个已有的项目时,你可能会遇到几个结果,这些是可能出现的后果及解决方案:

不能使用retain, release, 或autorelease。这是一个特征,而且以下代码也是不允许的这样的代码也是不允许的:

while ([x retainCount]) { [x release]; }
不能使用dealloc。

一般情况下,对于单例模式或者需要替换一个对象的时候,你会在init函数里面调用dealloc函数。对于单例模式,你可以使用共享模式来替代。因为后者在init里面不需要调用dealloc,在你从新对self赋值的时候,原内存就被释放,在init方法中,你并不必须调用dealloc,因为你重构self时,这个对象将会被释放。

不能使用NSAutoreleasePool 对象。使用新的@autoreleasepool{} 来代替。 它会强制使用一个块在你的autorelease pool,它的速度比NSAutoreleasePool快6倍。甚至@autoreleasepool 还可以在手动内存管理模式下工作。所以无脑使用速度更快的@autoreleasepool来替换掉之前的那些“性能杀手”。

迁移控制可以使用NSAutoreleasePool但它不能处理复杂的需要考虑的转换,或者用于当变量在 @autoreleasepool的body里被定义的转换之后

ARC要求在init方法中把[super init]赋值给self。下面的例子是错误的init方法

[super init];
应该修改成:

self = [super init];
修改后应对,self做nil值检查:

self = [super init];
if (self) {
...
你不能自定义实现retain或release方法。实现自定义retain或release方法会破坏weak指针。有下面几个常见的原因来说明为什么不要自定义implementations:

性能。

请不要再自定实现这些方法;NSObject中实现retain 和 release 要更快。如果你使用有问题,你应该去解决bug。

实现weak指针系统。

使用__weak来代替。

实现单例class.

使用共享模式代替。或者使用类来代替实例函数,来避免对所有的对象分配内存。

如果你觉得你必须实现自定义retain或release 方法,那么你必须在你的class中实现下面这个方法:

-(BOOL)supportsWeakPointers { return NO; }
这个方法阻止为你的类生成weak指针。但是强烈建议你使用其他的方式来避免实现这些函数。

你不能在C语言的结构体中使用strong ids。

举个例子,下面的代码,编译时会报错:

[pre]struct X { id x; float y; };[/pre]
这是因为,x默认是strongly retained的,当你通过一组完成free操作的代码,传递一个指针进这些结构体,每个id都必须在struct被释放前被释放。但是编译器不能可靠的完成这些,所以结构体中的strong ids在ARC模式中被完全禁止了,必须先释放这些x指向的内存,但是由于是ARC模式,编译器不能安全的去做这些事,所以这些内存泄漏了,所以在C语言的结构中,ARC禁止使用强指针,下面是可能的解决方案:

使用Objective-C的对象来代替。

这是最最最好的方法。

如果使用Objective-C对象不是最优化的选择, (比如你想要一个大量数组的结构体) ,这时用void* 代替。

这需要使用显示的转换,下面会讨论。

使用对象的引用__unsafe_unretained。

下面的方法可以用于这种比较常见模式:

复制代码

struct x { NSString *S; int X; } StaticArray[] = { @"foo", 42, @"bar, 97,...};

你可以这样定义结构:

struct x { __unsafe_unretained NSString *S; int X; }
这样的写法可能会有问题而且不安全,如果在指针里面的实例被释放了。但是这样做和常量字符一样是共识的很有用的东西。你不能直接进行id和void *的转换(包括核心功能中的类型)。这个问题的细节在 “Managing Toll-Free Bridging”里面讨论。

你不能直接进行id和void *的转换(包括核心功能中的类型)。这个问题的细节在 “Managing Toll-Free Bridging”里面讨论。

常见Q&A

我怎么理解ARC? 在哪调用retains/releases?

你可以不要再去想什么在哪调用retain/release,你可以花更多的精力来思考你的程序逻辑,对象“strong and weak” 引用, 对象的所属关系,循环引用等问题。

我还需要给对象写dealloc方法吗?

可能吧。

因为ARC不会自动malloc/free,不会管理Core Foundation objects的生存周期,文件描述符等等。你还是需要写dealloc方法去释放资源。

你不需要也不能去release实体变量,但是你需要在系统的类和没有使用ARC的代码中,调用[self setDelegate:nil]。

在ARC下,dealloc 方法不是必须的,也不能调用[super dealloc];super在运行时执行。

循环引用在ARC中还有效吗?

是的。

ARC自动管理retain/release,,也继承了循环调用。 幸运的是, ARC模式下的代码很少有内存泄漏,因为在声明的时候就已经决定了是否需要retain。

ARC模式下块如何工作?

在ARC模式下,你只能再栈上传递块,例如返回语句。你不需要再使用 Block Copy。但你还是必须在为arrayWithObjects: 传入栈的时候使用[^{} copy]和其他的retain功能的函数。

有一件事情需要提醒,在ARC模式下,__block NSString *S被保留了,它不是一个野指针。使用_block __unsafe_unretained NSString *S 或者 (更好的方式) __block __weak
NSString *S.

我能不能在雪豹Xcode上开发ARC模式的Mac OS程序?

不行。雪豹版本的Xcode 4.2不支持ARC。雪豹版本没有10.7的SDK,所以在为MAC OS X开发应用的时候不能使用ARC,但是这个版本支持为iOS开发的时候使用ARC。狮子(Lion)版本的是可以的,这意味着你需要在Lion系统中为雪豹构造一个ARC应用

我能在ARC模式的工程中创建C语言的数组么?

当然可以, 如下例所示:

复制代码

// Note calloc() to get zero-filled memory.__strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(sizeof(SomeClass *), entries);for (int i = 0; i < entries; i++) { dynamicArray[i] = [[SomeClass alloc] init];} // 当你完成时,将所有入口赋值为nil使得ARC释放对象for
(int i = 0; i < entries; i++) { dynamicArray[i] = nil;}free(dynamicArray);

有几点需要注意的是:

你需要写 __strong SomeClass ** 在某些情况下, 因为默认是__autoreleasing SomeClass **。

申请的内存空间必须用0填满。

在释放这个数组前,你必须设置每一个元素为nil(调用memset,并传入0是没有用的)。

你必须避免使用memcpy 和 realloc。

使用ARC不会不很慢?

这要看你怎么去理解快慢了。但是通常来说“no”,不慢! 编译器有效的排除了很多多余的retain/release的调用,并一直在加快在常规Objective - C代码运行投入很大的努力。尤其是比常规的“返回一个etain/autoreleased 对象”的模式要快得多,而且当调用方法是ARC代码,调用的对象实际上并没有投入autorelease池。

要注意的一个问题是,优化器不是工作在常规的debug设置里面,所以使用-O0 比-Os出现更多的retain/release。

ARC可以在ObjC++模式下工作吗?

可以,你甚至可以在类和容器中使用strong/weak id。ARC在编译时,会在复制构造函数和析构函数中加入retain/release方面的逻辑处理,来确保正常工作。有一点需要避免的就是,你不能为某些指针使用__strong,例如:

std::vector<__strong NSString*> V;
那些类不支持zeroing-weak的weak引用?

下面的类的实例不能使用zeroing-weak的weak引用

NSATSTypesetter, NSColorSpace, NSFont, NSFontManager, NSFontPanel, NSImage, NSMenuView,NSParagraphStyle,NSSimpleHorizontalTypesetter,NSTableCellView,NSTextView,NSViewController,NSWindow, andNSWindowController. 还有,OS X上的AV Foundation框架中所有类都不支持zeroing-weak的weak引用。

如果属性变量是这些类的实例的时候,使用assign来替代weak;作为变量,使用__unsafe_unretained来替代__weak。

此外,不用对NSHashTable,NSMapTable, 和NSPointerArray的实例做weak应用。

在写类似NSCell这样使用NSCopyOjbect的子类的时候,有什么需要特别关注的地方么?

没什么特殊的。 ARC来关心你以前增加额外的retains。通过ARC,所有复制方法应该只是复制的实例变量。

我可以为单独文件指定是否使用ARC么?

可以.

当你迁移一个久工程到ARC模式下, -fobjc-arc 编译开关被默认的设置在所有的Objective-C 源代码上。 你可以使用-fno-objc-arc 来为特殊的class停用ARC 。在Xcode的 target的“Build Phases”标签, 打开Compile Sources group,展开源代码列表, 双击你想要修改的源代码的名字,再弹出框里输入-fno-objc-arc,然后点Done按钮。


GC
(Garbage Collection)是否被Mac废弃了?

GC 在Mac OS X v10.7依旧可用.。但是强烈建议你在新工程中使用ARC。对旧的工程(使用手动内存管理或GC),建议你试着去改为ARC模式,然而,这是非零量的工作,你应该权衡与其他优先事项比较之后再去做。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: