Fork me on GitHub

iOS 中的 performSelector:withObject:afterDelay: 方法

  在做项目的时候大家应该都用到过 performSelector:withObject:afterDelay: 这个方法,不过这个方法也是有点小小的坑,最明显的一点就是:performSelector 方法如果调用了不存在的方法,编译器只会报警告不会报错,所以有可能造成运行崩溃,这个点大家应该都比较清楚。

  另外一个坑点藏的有点深,平时我们一般都是在主线程去调用这个方法,当然是没有什么问题的。但是当我们在子线程去调用的时候,就会出现一些问题:方法并没有执行,为什么会出现这种状况呢?

  这是因为子线程默认是没有开启 RunLoop 的,当 performSelector:withObject:afterDelay: 方法执行完毕后,线程可能已经死亡了,无法再去执行延时任务。

  解决的方法其实也很简单,获取该子线程的 RunLoop,给他添加一个 port,防止 RunLoop 自动退出,然后调用 RunLoop 的 run 方法,当然可以使用 runUntilDate: 方法,让线程及时退出。

Example:

1
2
3
// 在启动RunLoop之前,必须添加监听的输入源事件或者定时源事件,否则调用[runloop run]会直接返回,而不会进入循环让线程长驻。
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];

  最后一点,如果想要取消之前设定的延时任务,可以用 cancelPreviousPerformRequestsWithTarget:selector:object: 方法:

1
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(xxx) object:nil];
------------- 本文结束感谢您的阅读 -------------