戏言:
iOS开发已经到了一个ARC时代,一般不需要我们过多的去关注内存是怎么分配,怎么管理的。很长一段时间,我也不知道内存管理是什么鬼,但如果遇到这方面的问题,却找不到解决办法确实很头疼的。So,还是静下心来,好好学习吧,毕竟内功才是体现水平。
1. 引用计数
对于一块动态申请的内存,有一个人(指针)使用,就给这个内存的计数器加1,使用完成后,就给这个计数器减1,当这个内存的引用计数为0了,我们再释放他,这样,上面的问题就解决了。OC,就是使用引用计数这种方式来管理内存的。
生动的理解就是:举一个生活中的例子,我们一起去水库边烧烤,我把火点着了,当我们正在“水深火热”的烤着肉,一个电话来了,媳妇让我回家。于是,我跟你们说,你们懂的,哥要回去了,为了防止引发火灾,我要把火扑灭了。我相信,此时你们打死我的心都有。
我们能不能想到更好的方法,我不浇灭火,又不会引起火灾?
计数,虽然火是我生的,但我们有10个人一起用。那么,这堆火的计数为10,如果我,或者任何一个同学走了,让计数减1,变成9,8,7...这样,直到最后一个同学走,他在走之前将火灭了就好了。 这就是OC的内存管理方式,引用计数。
2.内存管理的黄金法则
对于引用计数来说,有一套内存管理的黄金法则:
The basic rule to apply is everything that increases the reference counter with alloc, [mutable]copy[withZone:] or retain is in charge of the corresponding [auto]release.
只要使用了alloc/retain/copy/mutableCopy, 创建了对象
那么就必须使用release进行释放,
———谁创建,谁负责释放
3.retain与retainCount
retain,将对象进项保留操作,也就是使对象的引用计数加1。
retainCount,打印一个对象的引用计数。
DSDog*dog=[[DSDog alloc]init];
NSLog(@"%lu",[dog retainCount]);//1 含有init,引用计数加1
DSDog *dog2=[dog retain];
NSLog(@"%lu",[dog2 retainCount]);//2 对象retain,引用计数加1
[dog2 release];
NSLog(@"%lu",[dog2 retainCount]);//1 release,引用计数减1
[dog release]; // 变为0 ,销毁对象
4.MRC和ARC
ARC (Automatic Reference Counting),自动引用计数,由xcode,帮我们去管理内存。
MRC (Manual Reference Counting),手动引用计数,我们手动管理内存。
Xcode 5.0 以后的版本默认是ARC模式
工程创建的时候是ARC的,我们如果想要MRC,需要进行如下设置。
选中工程 - target - Bulid Settings - 搜索:automatic reference counting或auto,将Objective-C Automatic Reference Counting改为NO。
5.@property retain,assign,copy展开
5.1@property (nonatomic, retain) DSDog *dog; 用来修饰ObjC对象。
则会展开如下:
- (void)setDog:(DSDog *)dog
{
if (_dog != dog)
{
[_dog release];
_dog = [dog retain];
}
}
5.2 assign展开:简单数据类型
@property (nonatomic, assign) DSDog *dog;
assign是直接复制,则会展开如下:
//简单数据类型 ,OC的内存管理对于简单的数据类型 int\float…, OC无效
- (void)setDog:(DSDog *)dog
{
_dog = dog;
}
5.3 copy展开 , 复制一份原来的对象
//copy 多用于字符串,Dict、Array
@property (nonatomic, copy)NSString *name;
- (void)setName:(NSString *)name
{
if (_name != name)
{
[_name release];
_name = [name copy];
}
}
6.自动释放池
原理:对象接收到autorelease消息时,它会被添加到了当前的自动释放池中,当自动释放池被销毁时,会給池里所有的对象发送release消息。
ObjC提供两种方法创建自动释放池:
方法一:使用NSAutoreleasePool来创建
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
//这里写代码
[pool release];
方法二:使用@autoreleasepool创建
@autoreleasepool {
//这里写代码
}
7.weak:ARC新引入修饰词,可代替assign,比assign多增加一个特性
strong:ARC新引入修饰词,可代替retain