http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.htmlAutomaticReferenceCounting(ARC)是一个编译器的功能,提供了对Objective-C对象的自动内存管理。ARC在编译期间自动在适当的地方添加Objective-C对象的retain和release操作代码。一.总结ARC在编译期间,根据Objective-C对象的存活周期,在适当的位置添加retain和release代码。从概念上讲,ARC与手动引用计数内存管理遵循同样的内存管理规则。ARC也无法防止strong引用循环。ARC还引入了新的修饰符来修饰变量和声明属性。变量的修饰符__strong,__weak,__unsafe_unretained,__autoreleasing,默认是_strong;声明属性的修饰符strong,weak,unsafe_unretained,默认是strong。Objective-C对象和CoreFoundation-style对象直接的转换。你需要显示地告诉编译器转换后对象的所有权,转换修饰符号:__bridge,__bridge_retained
或CFBridgingRetain,__bridge_transfer
或CFBridgingRelease
。
ARC支持的系统:Xcode4.2forOSXv10.6和v10.7(64位应用程序)、iOS4、iOS5。weak不支持OSXv10.6和iOS4。
Xcode提供一个把手动引用计数转换成ARC的工具,chooseEdit>Refactor>ConverttoObjective-CARC。
二.ARC概述你不需记住什么时候要用retain,release,andautorelease,ARC评估你的对象的生命周期,并在编译时自动插入适当的内存管理。编译器还为你生成相应的dealloc方法。一个Person类声明如下:@interfacePerson:NSObject |
@propertyNSString*firstName; |
@propertyNSString*lastName; |
@propertyNSNumber*yearOfBirth; |
@propertyPerson*spouse; |
@end |
|
@implementationPerson |
@end |
属性的默认修饰符是strong。一个contrived方法如下:-(void)contrived{ |
Person*aPerson=[[Personalloc]init]; |
[aPersonsetFirstName:@"William"]; |
[aPersonsetLastName:@"Dudney"]; |
[aPersonsetYearOfBirth:[[NSNumberalloc]initWithInteger:2011]]; |
NSLog(@"aPerson:%@",aPerson); |
} |
ARC负责aPerson和NSNumber对象的内存释放。三.ARC强制执行新规则1.不能显示调用dealloc([superdealloc]),执行或调用retain,release,retainCount,orautorelease;禁止使用选择器@selector(retain),@selector(release),等。你可以实现一个dealloc方法,来释放实例变量以外的资源,例如:系统类调用[systemClassInstancesetDelegate:nil]和未使用ARC编译的代码。在dealloc方法中,ARC在适当的地方添加release来负责释放实例变量。2.不能使用NSAllocateObject
和NSDeallocateObject类。
3.不能在C结构体中使用对象指针。使用Objective-C类代替C结构体。
4.id和void*之间要求显示转换。
使用__bridge,__bridge_retained或CFBridgingRetain,__bridge_transfer或CFBridgingRelease来显示转换。
5.用@autoreleasepool{}代替NSAutoReleasePool。
6.不能使用memoryzones。不再需要NSZone。7.实例变量的访问名称不能用new作为前缀,不能声明一个属性用new作为前缀。@propertyNSString*newTitle;//错误
@property(getter=theNewTitle)NSString*newTitle;//修改访问方法,正确
四.ARC推出新的对象生命周期修饰符1.属性声明修饰符:strong,weak,unsafe_unretained,默认strongstrong和retain相似,只要有一个strong指针指向对象,该对象就不会被销毁;(一个对象,要是没有任何一个strong引用指向该对象,将马上被销毁);weak,声明为weak的指针,weak指针指向的对象一旦被释放,weak的指针都将被赋值为nil;unsafe_unretained,用unsafe_unretained声明的指针,指针指向的对象一旦被释放,这些指针将成为野指针。//以下2行代码执行效果一样 @property(retain)MyClass*myObject; |
@property(strong)MyClass*myObject; |
|
//Thefollowingdeclarationissimilarto"@property(assign)MyClass*myObject;" |
//exceptthatiftheMyClassinstanceisdeallocated, |
//thepropertyvalueissettonilinsteadofremainingasadanglingpointer. |
@property(weak)MyClass*myObject; //声明unsafe_unretained属性 @property(nonatomic,strong)NSString*string1; @property(nonatomic,unsafe_unretained)NSString*string2; //执行如下代码后,self.string2成了野指针 self.string1=[[NSStringalloc]initWithUTF8String:"string1"]; self.string2=self.string1; self.string1=nil; NSLog(@"String2=%@",self.string2); |
为了避免strong(强引用)循环,parent对象strong(强引用)child对象,child对象weak(弱引用)parent对象。2.变量的修饰符__strong,__weak,__unsafe_unretained,__autoreleasing,默认是_strong__strong:强引用,只要有一个strong引用指向该对象,那么该对象就不会被销毁;__weak:弱引用,不能保持一个对象的存活期,当弱引用指向的对象没有强引用指向时,该弱引用指针被置为nil;__unsafe_unretained,跟__weak相似,只是该引用指针成为野指针。__autoreleasing,修饰传递给方法的参数引用(id*),方法返回时自动释放。a)变量定义格式如下:ClassName*qualifiervariableName; |
MyClass*__strongmyStrongReference;//__strong是默认修饰符,等价于MyClass*myStrongReference; MyClass*__weakmyWeakReference; |
MyClass*__unsafe_unretainedmyUnsafeReference; |
//string用NSString对象引用初始化后,由于没有strong引用指向该NSString对象,NSString对象马上就被释放,string被置为nil; |
NSString*__weakstring=[[NSStringalloc]initWithFormat:@"FirstName:%@",[selffirstName]]; |
NSLog(@"string:%@",string);//输出null |
b)__autoreleasing,方法的参数是个引用指针(id*):参数是个__autoreleasing的方法声明如下:-(BOOL)performOperationWithError:(NSError*__autoreleasing*)error; |
NSError*error;//或定义成NSError*_autoreleasingerror; |
BOOLOK=[myObjectperformOperationWithError:&error]; |
if(!OK){ |
//Reporttheerror. |
//... |
//编译器自动添加了临时__autoreleasing变量NSError*__strongerror; |
NSError*__autoreleasingtmp=error; |
BOOLOK=[myObjectperformOperationWithError:&tmp]; |
error=tmp; |
if(!OK){ |
//Reporttheerror. |
//... |
//返回_autoreleasing定义的变量-(NSString*)name{_autoreleasingNSString*str=[[NSStringalloc]initWithString:@"name"];returnname;}五.ARC编译模式下,iOS和MacOSX平台对Outlets(用户接口变量)的管理统一了strong:Nib文件所有者(File'sOwner)的顶层对象(top-levelobjects);weak:视图或其他窗口中的Outlets(用户接口变量);六.ARC编译模式下,堆栈变量初始化为nil。七.使用编译器标志启用和禁用ARC-fobjc-arc启用ARC-fno-objc-arc禁用ARCa)ARC编译选项项目文件的[BuildSettings]->[AppleLLVMcompiler4.1-Language]b)在ARC编译模式下,某些源文件禁用ARC八.Corefundationstyle对象与Objective-C对象的桥接转换(Toll-Freebridge)ARC不自动负责CoreFoundation-style对象(例如CFArrayRef
、CFMutableDictionaryRef、
CGColorSpaceRef、CGGradientRef
)的内存释放,你必须使用CFRetain
andCFRelease管理
CoreFoundation-style对象。Objective-C对象和CoreFoundation-style对象的转换,你需要显式告诉编译器转换后的对象的所有权。a)__bridge,只做类型转换,但是不修改对象(内存)管理权;b)__bridge_retained或
CFBridgingRetain,将Objective-C的对象转换为CoreFoundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;
c)__bridge_transfer
或
CFBridgingRelease
,将CoreFoundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。
九.手动转换项目支持ARCa)不能调用retain
,release
,autorelease
.方法;b)不能调用dealloc方法;例如:[superdealloc];c)用@autorelesepool{}代替NSAutoreleasePool;d)init初始化方法,[superinit]
改成self=[super
init];
self=[superinit];//正确 |
if(self){ |
... |
e)没有使用ARC,类的实例变量默认是assign,对象赋值给实例变量,不会改变对象的引用计数;使用ARC后,类的实例变量默认是strong,对象赋值给实例变量,会延长对象的存活周期。f)不能在C结构体中使用strongid;
structX{idx;floaty;};//错误 |
g)id和void*(includingCoreFoundationtypes)之间不能直接相互转换;h)Nib中的非顶层对象Outlets(用户接口变量),修饰符assign改为weak;顶层对象Outlets,修饰符retain改为strong。十.其他a)__weak
不支持这些类的对象
:
NSATSTypesetter
,NSColorSpace
,NSFont
,NSMenuView
,NSParagraphStyle
,NSSimpleHorizontalTypesetter
,andNSTextView
。
b)ARC不支持管理的内容:malloc
/free分配的对象
,CoreFoundation-style对象,filedescriptors。CoreFoundation-style对象,它是由C的struct定义的各种对象,主要来自于CoreFoundation框架(如CFArray或者CFMutableDictionaryRef类型),或者其它采用CoreFoundation命名规范的框架,如CoreGraphics(如,CGColorSpaceRef和CGGradientRef)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理