# 09.NSTimer与GCD

## 一: 常用延时调用的方式

* NSObject的performSelector...
  * 实际是在当前线程创建了一个Timer去执行任务
* NSTimer
  * +timerWithTimeInterval
  * +scheduledTimerWithTimeInterval
* GCDTimer
  * dispatch\_after

## 二: 非GCDTimer使用注意

* 必须有一个活跃的`RunLoop`

> `performSelector` 和`scheduledTimerWithTimeInterval` 都是基于RunLoop的. 主线程没关系,因为不会停止 如果在子线程的话需要手动开启RunLoop否则调用将会是无效的

* NSTimer的创建于撤销必须在同一个线程操作
* `performSelector`创建取消也必须在同一个线程操作
* 内存泄露问题
  * Timer的target会被Timer强引用
  * Timer被RunLoop强引用
  * 所以想在`dealloc`里去`invalidate` Timer是不可能的
  * 计时完成后手动去`invalidate`
    * RunLoop解除对Timer的引用
    * Timer解除对Target的引用

## 三: GCDTimer

* 系统会自动处理线程逻辑
* 无须关心RunLoop问题
  * block的循环引用还是要注意下
    * 缺点
    * 没有repeats选项
    * 直接使用代码比较多,最好封装一下

![](https://upload-images.jianshu.io/upload_images/595974-438c0a9cb7a27160.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)

## 四: 时间准确性

### NSTimer-较低

> CFRunloopTimerRef 底层基于 `mk_timer` 实现 基于RunLoop运行 使用之前必须注册到RunLoop,但RunLoop为节省资源并不会在非常准确的时机调用定时器,执行任务时,可能错过一个时间点只能等下个时间点再执行 NSTimer有个`tolerance`属性可以用于设置宽容度,可提高精准度

### GCDTimer-准确

### CADisplayLink-较准确

> CADisplayLink是一个执行频率（fps）和屏幕刷新相同（可以修改preferredFramesPerSecond改变刷新频率）的定时器，它也需要加入到RunLoop才能执行。与NSTimer类似，CADisplayLink同样是基于CFRunloopTimerRef实现，底层使用mk\_timer（可以比较加入到RunLoop前后RunLoop中timer的变化）。和NSTimer相比它精度更高（尽管NSTimer也可以修改精度），不过和NStimer类似的是如果遇到大任务它仍然存在丢帧现象。通常情况下CADisaplayLink用于构建帧动画，看起来相对更加流畅，而NSTimer则有更广泛的用处。

## 参考

> <https://www.jianshu.com/p/0c050af6c5ee> <https://www.cnblogs.com/kenshincui/p/6823841.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/za-xiang/nstimer-yu-gcd.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
