您的位置:首页 > 移动开发 > Objective-C

objective-c 内存管理小结

2013-08-03 20:12 211 查看
内存管理的黄金法则: 如果对一个对象使用了alloc, copy, retain 方法,那么必须使用相应的release 或 autorelease 释放

内存管理的概念:
内存管理是关于如何管理对象生命周期的编程原则.(主要是针对OC的对象,所有的对象都继承NSObject)

引用计数(retainCount)

引用计数是cocoa 中提供一个机制来表示对象被引用的次数,称为"引用计数"(refernce counting) 或 "保留计数"(retain counting) .引用计数的值表示对象有几个"人"在使用它.

当对一个对象使用 alloc, retain, copy 方法,对象的引用计数 +1 .
当对一个对象使用 release 或者 autorelease 方法,对象的引用计
数 -1.
当对象的引用计数为 0 时, 系统会自动调用 dealloc 方法销毁对象
-(void)dealloc
{
[super dealloc];
}

对象所有权

所有者是如何获得某对象的所有权的?
当一个所有者做了以下某个动作时,它就拥有了一个对象的所有权(ownership).
alloc, allocWithZone:,
copy, copywithZone:,
mutableCopy,
mutableCopyWithZone:, retain

如果你拥有了某个对象的所有权,在不需要某一个对象时,需要释放他们(release, autorelease)

如何持有对象:
example:
-(void)setA:(A *)a
{
if(_a != a)
{
[_a release];
_a = [a retain];
}
}
释放旧对象,保持新对象
当保留某对象时,需在dealloc方法中释放该对象
exp:
-(void)dealloc
{
[_a release]; //释放保留的对象
[super dealloc];
}

合成存取器

@property (argu1, argu2, argu3) NSString *name;
argu1:  automic 多线程环境下,存在线程保护(默认)
 nonautomic 多线程环境下, 不存在线程保护

argu2:  assign 直接复制 (默认)
-(void)setName:(NSString *)name{
_name = name;
}

 retain 保留对象
-(void)setName:(NSString *)name{
if(_name != name)
{
[_name release];
_name = [name retain];
}
}

 copy 复制对象
-(void)setName:(NSString *)name{
if(_name != name)
{
[_name release];
_name = [name copy];
}
}

argu3:  readwrite 生成 setter ,getter方法 (默认)
 readonly 只生成 getter 方法

 在dealloc 方法中,将[object release] 改写成 self.object = nil.

自动释放池( NSAutoreleasePool )

自动释放池的概念及作用:
自动释放池是OC的一种内存自动管理机制
当自动释放池销毁时,会对池中的每一个对象调用一次release方法.

自动释放池的原理:
自动释放池就像一个数组, 以栈的数据结构压入每个对象,采用 " 先进后出 " 的原则
自动释放池嵌套
autorelease会将对象添加到离他最近的自动释放池( 注意: 逻辑最近 )
exp:
NSAutoreleasePool *pool1 = [[NSAutoreleasepool alloc] init];
Person *person = [[Person alloc] init];
[person autorelease]; //添加到pool1中

NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
Dog *dog = [Dog alloc] init];
[dog autorelease]; //添加到pool2中

// 这里注意嵌套原则 ,pool2嵌套在pool1中,所有应该先释放pool2
[pool2 release];
[pool1 release];

处理大量数据的例子
exp:
NSAutoreleasePool = *pool = [[NSAutoreleasePool alloc] init];
for(int i = 0; i < 1000000; i++)
{
if(i % 1000 == 0)
{
[pool release];
pool = [[NSAutoreleasePool alloc] init];
}
NSArray *array = [[NSArray alloc] init];
[array autorelease];
}
[pool release];

循环引用

当对象A retain 对象B,同时 对象B retain 对象A.这时两个对象A 和 B都没办法得到释放.这种情况我们称之为循环引用. 因此,使用代理设计模式,我们通常使用assign 使其中的一个运用直接赋值.

数组的内存管理

当数组添加一个元素( 对象 )时,会对该元素进行 retain ,对象引用计数 +1
当数组删除一个元素( 对象 )时,会对该元素发送一次release消息, 对象引用计数 -1.
当数组删除所有元素( 对象 )时,会对数组中每一个元素发送一次release消息,对象引用计数 -1.
当数组release 时,会对数组中的每一个元素( 对象 )发送一次release消息, 对象引用计数 -1.

内存中的区域划分

栈区(stack): 由系统自动分配和释放, 存放 方法的参数值,局部变量的值等. 采用 " 先进后出 " 的原则. 特点: 有序,速度快,容量小
堆区: 一般由程序员分配和释放,如果不释放,则出现内存泄露. 程序退出时,系统会收回你的内存. 特点: 无序, 速度慢, 容量大.
静态存储区: 全局变量( 外部变量 )和静态变量都存放在静态区域. (注意: 未初始化的全局变量 和 静态变量存放在一起, 已初始化的存放在一起.) 当程序退出时,系统回收.
常量区: 存放常量的内存区域,当程序退出时,系统回收 (注意: 当 const 在修饰的 局部 常量数据类型时, 该数据存放在栈区 ,生命周期与该区域有关)
代码区: 存放二进制代码的区域

ARC

ARC自动引用技术(automatic reference counting), 当你在编译程序时提供自动管理内存功能, 它会为代码自动加入内存的控制代码,控制对象的生命周期.如此一来,大大简化了内存管理的步骤.(注意: 版本支持是在IOS4(不支持弱引用) , IOS5上).

新语法的内存管理

如下程序:
 NSArray *array = @[@12, @34, @56, @78];
创建数组对象时,由XCODE自动为我们调用了autorelease 方法,不需要我们去手动释放.

 NSMutableArray = *mutableArray = [@[@12, @34, @56, @78] mutableCopy];
代码可拆分为:
NSArray *array = @[@12, @34, @56, @78];
NSMutableArray = *mutableArray =[array mutableCopy]
由于对象调用了mutableCopy方法,所有需要我们手动调用一次release 方法来释放该对象,同时系统会为mutableArray 调用一次autorelease 方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: