1. 内存泄漏的定义
程序中已动态分配的堆内存因为某种原因程序未被释放或者无法释放,造成内存浪费,导致程序运行缓慢或者崩溃等严重后果。
2. OC中内存泄漏的几种情况和解决办法
2.1 对象间的循环引用
2.1.1 普通对象的循环引用
解决方法是将对象之间引用环的某一强引用(strong)改为弱引用(weak)。
// ClassA
@property (nonatomic, weak) ClassA * a;
// ClassB
@property (nonatomic, strong) ClassB * b;
ps:强引用表示从属关系,引用对象拥有被引用的对象。
弱引用则暗示引用对象不拥有被引用的对象。
一个对象的寿命是由它被强引用多少次来决定的。只要对象还存在强引用,就不会释放该对象。
注意:但是对象之间的引用如果都是强引用就会发生强引用循环,导致该对象的内存无法释放,会造成内存泄漏的问题;解决方法是:一个对象使用强引用,一个对象使用弱引用,因为一个对象未被强引用时,该对象将被释放,对该对象的所有弱引用都会设定为 nil。
2.1.2 block循环引用
对象持有block,而block中有直接或简介的访问了该对象,造成循环引用;解决方法在block内,用该对象的弱引用。
typedef int (^MySomeBlock) (int);
__weak typeof(self) weakself = self;
self.block = ^int(NSInteger i) {
weakself.window;
return i;
};
2.1.3 delegate循环引用问题
2.2NSNotification的观察者忘记移除
在合适的时机将观察者进行移除,比如在viewWillDisappear或者dealloc中。观察者一种是不带block的,这类观察者iOS9.0后无需手动移除。另一种是block块的观察者,需要手动移除;如果不移除,由于观察者强持有block块,这样造成每个观察者都持有一个block。如果接收到通知,多个观察者都会调用该block,造成重复调用。所以,一定要合适的时机移除该类观察者。
2.3 NSTimer循环引用
NSTimer强持有对象,对象强持有NSTimer时会造成循环引用;解决方法是在适当的时候调用NSTimer的invalidate方法;不要在强引用环中对象的dealloc中调用,否则不会打破引用环。
2.4 非OC对象内存处理
其它的对于CoreFoundation框架下的某些对象或变量需要手动释放(如CGContextRelease);C语言代码中的malloc等分配的内存,需要手动free释放内存。
+ (UIImage *)imageFromColor:(UIColor *)color size:(CGSize)size {
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGContextRelease(context);
return img;
}
2.5 大次数循环内存暴涨问题
当循环次数较大,且循环体内局部变量占用内存较大时,会出现该问题;解决方法是将循环体代码放入缓存池中。
NSMutableArray * imageList = [NSMutableArray new];
for (NSInteger i = 0; i < 10000; i++) {
@autoreleasepool {
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:@"image_%ld", i]];
[imageList addObject:image];
NSLog(image);
}
}
2.6 加载大图片或者多个图片
使用imageWithContentsOfFile替换imageNamed。
作者:苍眸之宝宝
链接:https://www.jianshu.com/p/5cc864c1cd94
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。