一、block 系列
在 ARC 下,当
block
获取到外部变量时,由于编译器无法预测获取到的变量何时会被突然释放,为了保证程序能够正确运行,让block
持有获取到的变量,向系统显明:我要用它,你们千万别把它回收了!然而,也正因block
持有了变量,容易导致变量和block
的循环引用,造成内存泄露!
二、performSelector 系列
performSelector 顾名思义即在运行时执行一个 selector,最简单的方法如下
- (id)performSelector:(SEL)selector;
这种调用 selector 的方法和直接调用 selector 基本等效,执行效果相同
[object methodName];
[object performSelector:@selector(methodName)];
三、addObserver 系列
addObserver 即 Objective-C 中的观察者,此系列常见于 NSNotification、KVO 注册通知。注册通知时,为了防止 observer 被突然释放,造成程序异常,需要持有 observer,这是造成内存泄露的一个隐患之一。
所以为什么需要在代码的 dealloc 方法中移除通知,原因就在于此。
NSNotificationcenter 需要 removeObserver 的原因是如果不移除的话,被观察者那么还会继续发送消息。如果此时观察者已经释放,消息会转发给其他对象,有可能造成严重的问题Effective Objective-C Notes:理解消息传递机制
四、NSTimer
在使用 NSTimer addtarget
时,为了防止 target
被释放而导致的程序异常,timer
会持有 target
,所以这也是一处内存泄露的隐患。
// NSTimer 内存泄露
/**
* self 持有 timer,timer 在初始化时持有 self,造成循环引用。
* 解决的方法就是使用 invalidate 方法销掉 timer。
*/
// interface
@interface SomeViewController : UIViewController
@property (nonatomic, strong) NSTimer *timer;
@end
//implementation
@implementation SomeViewController
- (void)someMethod
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(handleTimer:)
userInfo:nil
repeats:YES];
}
@end
五、try...catch
Apple 提供了 错误处理(NSError)和 异常处理(NSException)两种机制,而 try...catch 就是使用 exception 捕获异常。NSError 应用在在绝大部分的场景下,并且这也是 Apple 所推荐。那什么时候用 NSException 呢?在极其严重的直接导致程序崩溃情况下才使用,并且无需考虑恢复问题。