[转载]对iOS开发中内存管理的一点总结与理解
2015-06-14 23:39
573 查看
对iOS开发中内存管理的一点总结与理解
做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作的理解是衡量一个程序员成熟与否的一个标准。好了,闲话不说,下面进入正题。 众所周知,ObjectiveC的内存管理引用的一种叫做“引用计数“ (Reference Count)的操作方式,简单的理解就是系统为每一个创建出来的对象,(这里要注意,只是对象,NSObject的子类,基本类型没有‘引用计数’)记录一个引用计数,初始化这个对象的时候会调用alloc方法,系统在alloc方法里会将这个对象的引用计数+1;例如:UIView *myview = [UIView alloc] init]; 这里创建的对象myview它现在的引用技术就是1。所有的对象可以调用[xxx reatin];来使自身的引用计数+1。也可以调用[xxx release];让自身的引用计数-1.如果一个对象的引用计数为0,那么这个对象立即(记住,是立即)会被系统回收掉。除了[xxx reatin];会将对象的引用计数+1之外还有很多方法会将对象的引用技术+1,举两个最常用的:[self.view addSubView:myView];这个方法会将myView的引用计数+1。 NSArray类里的[array addObject:myView];也会将引用计数+1。下面我会用代码说明一下几个比较容易出错的地方。(一)临时变量对象的引用计数说明
UIView *v = [[UIView alloc] init]; //分配后引用计数为1
[objc] view plaincopy
[self.view addSubview:v]; //这儿引用计数加1,为2
[v release]; //这儿引用计数为-1为1
最后系统在回收self.view的时候,会先回收其subView,所以self.view被回收时v的引用计数是0,v就会立即被回收。
(二)成员变量对象的引用计数说明
[objc] view plaincopy
v = [[UIView alloc] init];
[self.view addSubview:v];
[v release];
如果在dealloc里调用了[v release];那么就多release了,会crash.
(三)如果v是类的属性,并且是声明的时候是assgin
[objc] view plaincopy
@property (nonatomic, assign) UIView *v; 这儿是assign, 然后分配内存的时候如果是这样
self.v = [[UIView alloc] init];//计数为1
[self.view addSubview:self.v];//计数为2
[self.v release];//计数为1
这时不需要在dealloc里[self.v release];因为assign声明的对象引用计数不会自动+1.当self.view被回收时,self.v的引用计数就会变成0;V就会被系统回收掉。
(四)如果v是类的属性,并且是声明的时候是reatin的
[objc] view plaincopy
@property (nonatomic, retain) UIView *v; 或 @property (nonatomic, copy) UIView *v;声明的属性,那么这样分配内存
v = [[UIView alloc] init];
[self.view addSubview:v];
[v release];这样与a是一样情况,不需要在dealloc里释放。
[objc] view plaincopy
但如果是
self.v = [[UIView alloc] init];
[self.view addSubview:self.v];
[self.v release];加了个self,那么就要在dealloc里[v release];因为如果属性用reatin声明的时候,用self.初始化的时候对象的引用技术会自动+1。self.v = [[UIView alloc] init];//这个时候引用计数为2
下面聊聊autorelease,autorelease是objectiveC语言的一个比较特殊的机制,也是理解ObjectiveC内存管理的关键,Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对的,其实autorelease就是一个延迟释放的机制,比较好的介绍autorelease的文章:http://developer.51cto.com/art/201007/212523.htm 这篇文章个人认为autorelease讲解的比较详细,也易于理解。推荐大家看看,这里除了这篇文章之外我还要谈谈我对autorelease的一些理解。我理解的是,系统在执行每一个函数的时候,会自动开启一个autoreleasePool(记住是每一个函数的运行都会开启一个autoreleasePool,而不是每一个类开启一个,这一点很关键),在这个函数当中创建的所有用autorelease声明的对象都会放进这一个的池当中。当函数运行完的时候,这一个autorelasepool 会被drain 掉,那么池中所有引用计数为0的(千万记住是引用计数为0)对象,就会被系统回收掉。写到这里很多人就会程序猿就会质疑我这个说法了,比如我在某一个UIViewController类的viewDidLoad函数里面写了:UIView *myView = [[UIView alloc] init] autorelease];[self.view addsubView:myView]; 的时候,当viewDidLoad函数执行完,为什么myView对象没有被回收。这是因为:因为调用了[self.view addsubView:myView];所以这时myView的引用计数变成了2,当函数执行完,autorelease被drain掉的时候,自动释放池内所有的对象都会调用release方法,这时所有的对象的引用计数-1,如果这时对象的引用计数为0那么它会被系统回收,如果不为0,那么他还回被保留,也就是说自动释放池中的对象不会因为自动释放池的销毁而被销毁,自动释放池的对象只是被延迟释放了,池中对象的释放也得满足引用计数的机制。
以上就是我对IOS内存管理的一些简单的理解,不对之处欢迎大家指正,咱们互相提高。
相关文章推荐
- ios 获取屏幕的属性和宽度
- iOS开发笔记——CocoaPods详解_制作篇
- 初探 iOS8 中的 Size Class
- iOS开发笔记--CocoaPods详解_进阶篇
- iOS开发笔记--CocoaPods详解_使用篇
- iOS学习------监听中心的简单实用
- ios view的frame和bounds之区别(位置和大小)
- iOS时间那点事
- NSURLSession简单讲解 -----iOS
- 如何解决NO EPCS LAYOUT DATA --- LOOKING FOR SECTION [EPCS-XXXXXX]
- xcode6 iOS sdk8.1隐藏系统状态栏
- iBokan_ios80_自学系列_1(部分循环结构)
- iOS系统进入安全模式的方法
- IOS自动布局进阶系列视频教程-03自动布局-内容吸附详解【海鹰】
- IOS自动布局进阶系列视频教程-02scrollView自动布局中的应用
- IOS自动布局进阶系列视频教程-01自动布局概述
- IOS不用AutoLayout也能实现自动布局的类(2)----MyFrameLayout横空出世
- OC基础:实例变量和成员变量的区别 分类: ios学习 OC 2015-06-14 17:59 16人阅读 评论(0) 收藏
- Xcode6模拟器iOS8键盘出不来问题
- iOS NSString的常用用法