Block的循环引用
循环引用就是当self 拥有一个block的时候,在block 又调用self的方法。这个时候self强引用了block,而在block中使用self也会强引用self。这样就会产生循环引用,导致两个对象都得不到释放。
self.myBlock = ^{ [selfdoSomething]; };
解决的方法:掐断其中的一条强引用,使之变成弱引用,变成这样,就打破了循环引用:
__weaktypeof (self) weakSelf =self;
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.layeraddAnimation:transition forKey:"myAnimation"];解决办法是,在ViewController关掉的时候,停止这个animation
-(void)viewWillDisappear:(BOOL)animated { [self.view.layerremoveAllAnimations];}
非OBJC对象
ARC是自动检测OBJC对象的,非objc对象就无能为力了,比如C或C++等。
C语言使用 malloc 开辟,free释放。
C++使用new 开辟,delete释放。
但是在ARC下,不会添加非OBJC对象释放语句,如果没去释放,也会造成内存泄露。