42、多用GCD,少用performSelector系列方法
NSObject定义了几个方法,可以推迟执行方法调用,也可以指定运行方法所用的线程。这些功能原来很有用,但是在出现了大中枢派发及块这样的新技术之后,就显得不那么必要了。虽说有些代码还是会经常用到它们,但笔者劝你还是避开为妙。
如果选择子是在运行时决定的,那么就能体现出此方法的强大之处了:
SEL selector;
if ( /* some codition */ ) {
selector = @selector(newObject); // 需要释放
} else if ( /* some other codition */ ) {
selector = @selector(copy); // 需要释放
} else {
selector = @selector(someProrperty); // 不需要释放
}
id ret = [object performSelector:selector]; 这种编程方式看起来比较灵活,但是在ARC模式下会发出警告:
warning: performSelector may case a leak because its selector
is unknow [-Warc-performSelector-leaks] 因为编译器并不知道将要调用的选择子是什么,不了解其方法签名及返回值,甚至连私发欧有返回值都不清楚。所以没办法用ARC的内存管理规则来判定返回值是不是应该释放。鉴于此,ARC采用了比较谨慎的做法,就是不添加释放操作。因而可能导致内存泄露。
这个问题很容易忽视,而且就算用静态分析器,也很难侦测到随后的内存泄露。(所以需谨慎使用performSelector方法)
大中枢GCD出现之后,performSelector系列方法所提供的功能,都可以用GCD实现:
// 延迟执行
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^(void){
[self doSomething];
});
// 把任务放到主线程执行
dispatch_async(dipatch_get_main_queue(), ^{
[self doSomething];
});要点:
preformSelector系列方法在内存管理方面容易有疏失。它无法确定将要执行的选择子具体是什么,因而ARC编译器也就无法插入适当的内存管理方法performSelector系列方法所能处理的选择子太过局限了,选择子的返回值类型及发送给方法的参数个数都受到限制如果想把任务放在另一个线程上执行,那么最好不要用
preformSelector系列方法,而是应该把任务封装到块里,然后调用大中枢派发机制的相关方法来实现
Last updated
Was this helpful?