一个应用分配的可用内存是有限的,所以我们要释放那些不用的内存。所以开发中内存优化就显得尤为重要。那我们常用的优化方式有哪些呢?
(注意本文的讨论都是基于ARC的)
自动引用计数器
ARC开发环境下,之所以能自动释放内存,就是因为有自动引用计数器的存在,其内部判断对象是否销毁的条件就是自动应用计数器是否为0。
野指针问题:野指针就是指向"垃圾"内存(不可用内存)的指针,不是NULL指针
weak和assign都是弱引用,他们有什么区别?
weak:声明的变量对象释放后自动清空, 赋值为nil
assign:实际是__unsafe_unretained类型的,声明的变量对象释放后不会自动赋值为nil, 会造成野指针错误!
1、打开僵尸对象
通过打开僵尸对象,我们可以检测出一些野指针问题
打开方式
比如下面这段代码运行就会报错
野指针问题.png所以,开发中delegate用weak来修饰
2、静态检测
其实有些内存泄漏也可以用静态方法检测出来,静态检测分为手动检测和自动检测
手动检测方式:快捷键command + shift + B
自动检测方法:build setting --> analyze during building 设为YES
,这样每次运行代码都会检测内存泄漏问题,具体如下图
设置了静态检测就会看到类似下图的效果
静态检测.png3、动态检测
通常循环引用通过静态检测是检测不出来的,所以我们需要用到动态检测。动态的方式我们可以通过instrument和一些第三方。常用的第三方就是MLeaksFinder
instrument检测内存的使用方法这里就不累赘了,网上大把的资料
我们主要讲讲MLeaksFinder的使用,在github上就能收到,其实现原理主要是依赖runtime。从github下载后,再讲库文件拖到项目里就可以自动检测了。
MLeaks.png4、析构方法的打印
- (void)dealloc {
NSLog(@"[CycleRefViewController dealloc]")
}
在dealloc方法中打印,看是否有输出,要是没有输出那就存在内存泄漏。如果上面的方式都无法找出内存泄漏的地方,我们可以通过注释代码的方式查找。
具体操作步骤:猜想可能造成内存泄漏的地方,注释,看dealloc方法是否打印。这种方式可能比较盲目,但是是可靠。实在不知道可以代码在哪里,可以选择注释一半的代码,用二分思想来处理这个问题。
5、补充
并不是所有的block用self就会造成循环引用,只有相互强引用才会发生循环引用。比如下面用self就不会造成循环引用
Block b = ^{
[self doSomework];
};
使用block时还要注意一些隐式调用self的方式,比如 _xxx 。
self.block = ^{
_obj = [GVObject new];
};
这里就会造成循环引用
网友评论