1.循环引用
常见于两个VC相互引用,通过@class解决;
block 循环引用,通过__weak解决。
Use Weak References to Avoid Retain Cycles
2.发生异常时
使用@try{}@catch{},当异常发生时,无法释放对象。
在ARC下,无法在@finally{}里边调用release方法,只能通过添加编译标识:-fobjc-arc-exceptions,添加之后会产生大量额外代码,一般情况不要开启改标识。如果你必须要开启改标识来保证不出现异常崩溃,那你应该重新审视你自己的代码,你的代码肯定是有问题的。一般只有在这种情况下使用异常捕获:如果不捕获异常应用就会终止。如果出现这种情况,应用都终止了,还担心啥内存泄漏。而且,这中情况将要发生时,也没有一个合适的时机来添加代码来使得异常变得安全。
3.CoreFoundation对象没有调用CFRelease释放
CoreFoundation里边是纯 C 的API,需要自己释放。
4.heap(堆)上分配的内存没有调用free释放
堆上分配的内存需要自己手动释放。
5.大次数循环时创建了很多临时变量没有释放
Use Autorelease Pool Blocks to Reduce High-Memory Waterline
在循环内部添加@autoreleasepool{/*...*/}。
6.数据库、connection、socket 用完没有关闭,文件描述符(file descriptors)用完没有释放。
7.调试模式下开启僵尸调试
NSZombieEnabled=“YES” (Enable Zombie Objects),开启之后对象占用的内存不会被释放。
8.定时器使用完没有调用 invalidate 方法
如果NSTimer的target指向self,而该定时器赋给了该类的一个实例变量,那么timer将引用当前类,当前类的实例变量又引用了timer,就造成了循环引用。您可以授权其他对象来调用invalidate方法,但是什么时机调用您是不知道的。所以该循环引用其实无法很好地解决,不过您可以考虑给NSTimer添加一个类别,添加一个用block实现的定制方法。
@interface NSTimer (LLBlocksSupport)
+ (NSTimer *)ll_scheduledTimerWithInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:repeats;
@end
@implentation NSTimer (LLBlocksSupport)
+ (NSTimer *)ll_scheduledTimerWithInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:repeats
{
return [self scheduledTimerWithInterval:interval
target:self
selector:@selector(ll_blockInvoke:)
userInfo:[block copy]
repeats:repeats];
}
+ (void)ll_blockInvoke:(NSTimer*)timer {
void (^block)() = timer.userInfo;
if (block) {
block();
}
}
@end
这样,target是NSTimer自己,就不会导致循环引用了。
9.播放器使用完没有调用 stop 方法
可用Xcode的Instruments里边的Leaks检测内存泄漏。要用代码检测泄漏,请 到这里。