IOS ARC下内存泄露总结

Block的循环引用

循环引用就是当self 拥有一个block的时候,在block 又调用self的方法。这个时候self强引用了block,而在block中使用self也会强引用self。这样就会产生循环引用,导致两个对象都得不到释放。

 self.myBlock = ^{
    [self doSomething];
  };

循环引用

解决的方法:掐断其中的一条强引用,使之变成弱引用,变成这样,就打破了循环引用:

__weak typeof (self) weakSelf = self;

打破循环引用

还有一些系统的Block,这些Block中不用做特殊处理就可以直接使用self,因为这些系统的Block由系统strong引用,我们的代码没有强引用它

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"Self.a %@", self.a);
});

系统Block

NSTimer未释放

在使用 NSTimer addtarget 时,为了防止 target 被释放而导致的程序异常,timer 会强引用 target,所以这也是一处内存泄露的隐患。解决方法是使用线程安全的MSWeakTimer,然后在dealloc中主动调用invalidate

- (void)dealloc {
    [timer invalidate];
}

performSelector 系列

performSelector分静态调用和动态调用,以下这种调用 selector 的方法和直接调用 selector 基本等效,执行效果相同,不存在内存泄露

[object methodName];
[object performSelector:@selector(methodName)];

还有一种动态绑定方式,编译器不知道即将调用的 selector 是什么,不了解方法签名和返回值,甚至是否有返回值都不懂,所以编译器无法用 ARC 的内存管理规则来判断返回值是否应该释放。因此,ARC 采用了比较谨慎的做法,不添加释放操作,即在方法返回对象时就可能将其持有,从而可能导致内存泄露。在ARC下编译会告警:
warning: performSelector may cause a leak because its selector is unknow [-Warc-performSelector-leak]

-(void)method:(SEL)selector {
    [object performSelector:selector];
}

解决方式是使用函数指针,显示的声明这个函数

IMP imp = [viewController methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;
func(viewController, selector);

Delegate循环引用

把delegate声明为strong属性导致了循环引用

@property (nonatomic, strong) SampleViewController *delegate;

解决方法很简单把strong改成weak就行

@property (nonatomic, weak) SampleViewController *delegate;

循环未结束

如果某个ViewController中有无限循环,也会导致即使ViewController对应的view关掉了,ViewController也不能被释放。这种问题常发生于animation处理。

CATransition *transition = [CATransition animation];
transition.duration = 0.5;
tansition.repeatCount = HUGE_VALL;
[self.view.layer addAnimation:transition forKey:"myAnimation"];

解决办法是,在ViewController关掉的时候,停止这个animation

-(void)viewWillDisappear:(BOOL)animated {
    [self.view.layer removeAllAnimations];
}

非OBJC对象

ARC是自动检测OBJC对象的,非objc对象就无能为力了,比如C或C++等。
C语言使用 malloc 开辟,free释放。
C++使用new 开辟,delete释放。
但是在ARC下,不会添加非OBJC对象释放语句,如果没去释放,也会造成内存泄露。

猜你喜欢

转载自blog.csdn.net/dlmlzz09/article/details/54575703