ARC
ARC是iOS 5推出的新功能,全称叫 ARC(Automatic Reference Counting)。简单地说,就是编译阶段自动做了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。就ARC并不是GC,不是运行时内存管理,不会做malloc/free的工作,它只是一种代码静态分析(Static Analyzer)工具。
比如,我们生成一个对象:
编译器会给我们添加上retain/release/autorelease
比如,block的写法,编译器背后给我们做的事:
ARC之前的手工管理内存
我们需要手动retain和 release对象。如下:
// First you create an object, which you then own ("retain")
// Retain count = 1
Customer *newCustomer = [[Customer alloc] init];
// Next, you do something with the new object, such as add it to an
// array, which also now retains it. Retain count = 2
[customerArray addObject:newCustomer];
// When finished with the object, you relinquish (release) ownership.
// Retain count = 1
[newCustomer release];
// At some point customerArray is also released, releasing all of the
// objects it contains. Retain count = 0, and the original object is
// finally deallocated
[customerArray release];
这个过程很容易出错。所以苹果引入ARC,在编译阶段自动帮我们做retain/release的工作,如下图,减少了很多代码。
手工引用计数规则
- 用“alloc”, “new”, “copy”, or “mutableCopy”等方法生成object的时候,object 的引用计数为1.
When youcreate
an object, it has a retain count of 1. You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example,alloc
,newObject
, ormutableCopy
).
- 向object发送retain消息,它的引用计数+1.
When you send an object aretain
message, its retain count is incremented by 1.
向object发送release消息,引用计数-1.
When you send an object arelease
message, its retain count is decremented by 1.向object发送autorelease消息,引用计数-1.当引用计数为0,object被释放 。
When you send an object aautorelease
message, its retain count is decremented by 1 at the end of the current autorelease pool block.If an object’s retain count is reduced to zero, it isdeallocated
.
ARC:自动引用计数
ARC模式下,引用计数的规则还起作用,只是编译器做retain,release,autorelease的工作。
WWDC Adopting Automatic Reference Counting
ARC基本规则
参考:
Transitioning to ARC Release Notes
规则:
You cannot explicitly invoke dealloc, or implement or invoke retain, release, retainCount, or autorelease.
You cannot use NSAllocateObject or NSDeallocateObject.
You cannot use object pointers in C structures.
There is no casual casting between id and void *.
You cannot use NSAutoreleasePool objects.
You cannot use memory zones.
-
You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example,
// Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle;`
Is ARC slow?
It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneous retain
/release
calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.
引用类型:
Strong reference : 强引用指针增加对象引用计数。
Weak reference :弱引用指针不增加对象引用计数,对象被释放后,指针被置为nil
引用关键字:
__strong
:_strong修饰符表示对对象的“强引用”。持有强引用的变量在超出其作用域时被废弃,随着强引用的失效,引用的对象会随之释放
__weak
:
使用_strong修饰符的成员变量在持有对象时,很容易发生循环引用。
循环引用容易发生内存泄露。内存泄露就是应当废弃的对象在超出其生存周期后继续存在。
使用_weak修饰符可以避免循环引用。_weak修饰符还有另一有优点。在持有某对象的弱引用时,若该对象被废弃,则此弱引用将自动失效且处于nil被赋值的状态(空弱引用)。
__unsafe_unretained__
autoreleasing
使用关键字的格式,关键字在*号之后
MyClass * __weak myWeakReference;
MyClass * __unsafe_unretained myUnsafeReference;
循环引用
三种循环引用的模式:
- 对象之间有“父子关系
- Delegate模式
- Blocks
解决方法:
管理Autorelease Pools
使用autorelease pool 的场景:
程序不基于 UI framework.
If you are writing a program that is not based on a UI framework, such as a command-line tool.在循环中生成大量的临时变量,可以在for循环中用autorelease pool block。
If you write a loop that creates many temporary objects.
You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.-
Cocoa application中的每个线程维护自己的 autorelease pool block堆栈,所以开子线程需要生成自己的autorelease pool block.
You must create your own autorelease pool block as soon as the thread begins executing; otherwise, your application will leak objects. (See Autorelease Pool Blocks and Threads for details.)
对象转换
在iOS世界,主要有两种对象:Objective-C 对象和 Core Foundation 对象0。Core Foundation 对象主要是有C语言实现的 Core Foundation Framework 的对象,其中也有对象引用计数的概念,只是不是 Cocoa Framework::Foundation Framework 的 retain/release,而是自身的 CFRetain/CFRelease 接口。
这两种对象间可以互相转换和操作,不使用ARC的时候,单纯的用C原因的类型转换,不需要消耗CPU的资源,所以叫做 Toll-Free bridged
Transitioning to ARC Release Notes
__bridge` transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.
-
__bridge_retained
orCFBridgingRetain
casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.You are responsible for calling
CFRelease
or a related function to relinquish ownership of the object. -
__bridge_transfer
orCFBridgingRelease
moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC.ARC is responsible for relinquishing ownership of the object.