记录一些最近使用OC时涉及到的内容,算是巩固和总结。
ARC内存管理
Cocoa使用引用计数(RC)方法来管理对象的生命周期,以达到内存管理的目的。
引用计数(RC)
对于内存中每个对象,都有一个整数与其相对应,这个数字就是它的引用计数(RC)。
当某段代码需要访问一个对象时,代码就将该对象的引用计数器值加1,表示“我要访问该对象”;当这段代码结束对该对象访问时,将对象的引用计数器减1,表示它不再访问该对象。当引用计数的值为0时,表示不再有代码访问该对象,此时该对象将被销毁,其占用的内存会被系统回收以便重用。
当使用alloc、new方法或者通过copy消息创建一个对象时,对象的引用计数值被设置为1,要增加对象的引用计数的值,可以给对象发送一条retain消息。要减少的话,可以给对象发送一条release消息。
当一个对象因其引用计数值归0而即将被销毁时,Objective-C会自动向对象发送一条dealloc消息。你可以在自己的对象中重写dealloc方法,这样就能释放掉已经分配的全部相关资源。一定不要直接调用dealloc方法,Objective-C会在需要销毁对象时自动调用它。
要获得一个对象的引用计数的值,可以发送retainCount消息。
autorelease pool
我们可以很容易地知道何时创建了一个对象,但常常很难确定在何时何处不再使用该对象而将其释放。
Cocoa中的自动释放池很好地解决了这一问题。NSObject类提供有以下方法:
1 | - (id) autorelease; |
该方法预先设定了一条会在未来某个时间发送的release消息,其返回值是接收这条消息的对象。这一特性与retain消息采用了相同的技术,使嵌套调用更加容易。当给一个对象发送
autorelease消息时,实际上是将该对象添加到了自动释放池中。当自动释放池被销毁时,会向该池中的所有对象发送relase消息。
其实有两种方法可以创建一个自动释放池:
- 使用 @autoreleasepool 关键字
- 通过NSAutoreleasePool 对象
在Foundation库中可以使用@autoreleasepool
,大括号作用范围内所有的代码都会放进这个自动释放池内:
1 |
|
如果使用NSAutoreleasePool
对象,需要手动创建和释放对象。当创建了一个自动释放池之后,该对象会自动成为当前激活的(active)自动释放池。当该自动释放池对象被销毁时,会释放池中的所有对象:
1 |
|
Cocoa内存管理规则
Cocoa内存管理的规则如下:
当你使用new、alloc或copy方法创建一个对象时,该对象的保留计数器的值为1。当不再使用该对象时,你应该向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被销毁。
当你通过其他方法获得一个对象时,假设该对象的保留计数器的值为1,而且已经被设置为自动释放,那么你不需要执行任何操作来确保该对象得到清理。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。如果你保留了某个对象,就需要(最终)释放或自动释放该对象。必须保持retain方法和release方法的使用次数相等。
当拥有一个对象时,只需要判断该对象的获得途径(怎样获得的),以及将要拥有这个对象多长时间:
获得途径 | 临时对象 | 拥有对象 |
---|---|---|
alloc/new/copy | 不再使用时释放对象(Release) | 在dealloc中释放对象(Release) |
其他方法 | 不需要执行任何操作 | 获得对象时保留(Retain) 在dealloc中释放对象 |
[NSMutableArray arrayWithCapacity]
和 [NSColor blueColor]
等都属于上表中的“其他方法”。
自动引用计数
自动引用计数(ARC)是苹果公司的内存管理解决方案。
ARC是在编译时进行工作的,它在代码中插入了合适的retain
和release
语句,就好像是你自己手动写好了所有的内存管理代码。不过,是编译器替你完成了内存管理的工作,程序在运行的时候。retain
和release
会像往常一样发挥作用。系统不会知道也不会关心这些命令是你写的还是编译器写的。
ARC是一个可选的功能,你必须明确地启用或禁用它。
ARC只对可保留对象指针(retainable object pointers,ROPs)有效。可保留对象指针主要有以下三种:
- 代码块指针
- Objective-C对象指针
- 通过
_attribute__((NSObject))
类型定义的指针
在代码中使用ARC,需要满足以下三个条件:
- 能够确定哪些对象需要进行内存管理
- 能够表明如何去管理对象
- 有可行的办法传递对象的所有权
代理传值
现有两个UIViewController,分别名为UIViewControllerFirst和UIViewControllerSecond,在First中点击某按钮后会创建Second并跳转。此时很容易实现由First向Second的传值(以及函数调用)。如果需要从Second向First传值(或函数调用),有很多种方法,如可以使用代理的方式,主要步骤为:
- 在Second中声明协议,协议中包含一个传递值的方法
- Second中声明代理
- First需要实现Second中的协议
- 将First设置为Second中的代理
- 在Second中调用代理实现的方法
UIViewControllerFirst.h:
1 | #import <UIKit/UIKit.h> |
UIViewControllerFirst.m:
1 | #import "UIViewControllerFirst.h" |
UIViewControllerSecond.h:
1 | #import <UIKit/UIKit.h> |
UIViewControllerSecond.m:
1 | #import "UIViewControllerSecond.h" |
单例模式
1 | @interface UploadManager : NSObject |
1 |
|
REFERENCE
http://www.cnblogs.com/andyque/archive/2011/08/03/2125728.html