ios中的内存管理搞的很繁琐,网上很多资料写的更繁琐,我简单的写一下。
ios的内存管理分为两个时代MRC和ARC
- MRC时代是完全由程序员管理内存,代码看起来写的非常冗长,给程序开发和维护带来了困扰
每块动态分配的内存都有一个计数器,当计数器为0⃣️的时候,系统就释放对象。
计数器+1的情况
1、alloc生成对象的时候需要,计数器自动置为1.
2、retain时加1
计数器-1的情况
1、调用release时,会-1
其他的地方跟c/c++是一样的,什么野指针、空指针,这里就不赘述了
2、ARC时代编译器会自动给我们加上release操作,代码看起来没有那么冗长了,但是编译器的智能有限,对于循环引用无能为力,程序员随时都需要关注内存有循环引用的地方,用weak修饰符打破这种循环引用,只持有,不增加计数器的值,但是这又带来一个问题,弱引用有时候又会被释放,所以有时候又需要转化的局部强引用(苦逼的程序员啊,脑力劳动一点没减少),当然你也可以strong方式引用,不用后将引用置为nil,这样手动释放也是一种办法。
常见的循环引用的地方
1、
情况一:delegate
delegate 是iOS中开发中最常遇到的循环引用,一般在声明delegate的时候都要使用弱引用 weak
或者assign
当然怎么选择使用assign还是weak,MRC的话只能用assign,在ARC的情况下最好使用weak,因为
weak修饰的变量在释放后自动指向nil,防止野指针存在
2、情况二:block
当某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身就产生了
循环引用问题
解决办法:
通过 __weak __block 去声明一个弱引用的self
_weak typeof(self) weakSelf = self;
self.blkA = ^{
//加一下强引用,避免weakSelf被释放掉
__strong typeof(weakSelf) strongSelf = weakSelf;
//不会导致循环引用.
NSLog(@"%@", strongSelf->_xxView);
};
多次调用的self的情况下需要转化称局部强引用
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
});
情况三:NSTimer
当你创建使用NSTimer的时候,NSTimer会默认对当前self有个强引用,所以在self使用完成打算
释放的时候,一定要先使用NSTimer的invalidate来停止,释放时间控制对self的引用
[_timer invalidate];