iOS定時器-- NSTimer 和CADisplaylink

iOS定時器-- NSTimer?和CADisplaylink

?

一、iOS中有兩種不同的定時器:

1. ?NSTimer(時間間隔可以任意設定,最小0.1ms)//?If?seconds?is less than or equal to?0.0, this method chooses the nonnegative value of 0.1 milliseconds instead.

2. ?CADisplayLink(時間間隔不能設置,與顯示器刷新頻率一直)

二、創建和啟動定時器的3種方式:

// 方式1

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(nextImage) userInfo:nil repeats:YES]; //會自動加入當前的runloop消息循環中,不用手寫[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

// 方式2

// 創建 NSTimer 對象

NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(test1) userInfo:nil repeats:YES];

//將剛創建的 NSTimer 對象加到消息循環中, 這樣就會自動啟動定時器

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

[runLoop addTimer:timer forMode:NSRunLoopCommonModes];

// 方式3

// 創建計時器對象

NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(test1) userInfo:nil repeats:YES]

// 每次調用一次 fire 執行一次 test1方法

[timer fire]; // 執行一次 test 方法

[timer fire]; // 執行一次 test 方法

[timer fire]; // 執行一次 test 方法

[timer fire]; // 執行一次 test 方法

?

三、關于NSRunLoop相關知識:

先看看NSTimer的兩個常用方法:

+ (NSTimer?*)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;?//生成timer但不執行

+ (NSTimer?*)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;?//生成timer并且納入當前線程的run loop來執行

?

NSRunLoop與timer有關方法為:

- (void)addTimer:(NSTimer?*)timer forMode:(NSString?*)mode;?//在run loop上注冊timer

?

理解run loop后,才能徹底理解NSTimer的實現原理,也就是說NSTimer實際上依賴run loop實現的。

主線程已經有run loop,所以NSTimer一般在主線程上運行都不必再調用addTimer: 。

但在非主線程上運行必須配置run loop,NSTimer在非主線程的main方法中使用,示例代碼如下:

- (void)main

{

  NSTimer *myTimer =?[NSTimer scheduledTimerWithTimeInterval:1.0?target:self?selector:@selector(timer:)?userInfo:nil?repeats:YES];

  NSRunLoop *runLoop =?[NSRunLoop?currentRunLoop];

  [runLoop addTimer:myTimer forMode:NSDefaultRunLoopMode]; //實際上這步是不需要,scheduledTimerWithTimeInterval已經納入當前線程運行。如果使用timerWithTimeInterval則需要

  while (xxx條件)

    [runLoop run];

}

實際上這個線程無法退出,因為有timer事件需要處理,[runLoop run]會一直無法返回。解決辦法就是設置一個截止時間:

[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];?//每隔10秒檢查下線程循環條件,當然時間值可以根據實際情況來定。

?

特別注意:

我們通常在主線程中使用NSTimer,有個實際遇到的問題需要注意。當滑動界面時,系統為了更好地處理UI事件和滾動顯示,主線程runloop會暫時停止處理一些其它事件,這時主線程中運行的NSTimer就會被暫停。解決辦法就是改變NSTimer運行的mode(mode可以看成事件類型),不使用缺省的NSDefaultRunLoopMode,而是改用NSRunLoopCommonModes,這樣主線程就會繼續處理NSTimer事件了。具體代碼如下:

NSTimer *timer =?[NSTimer?timerWithTimeInterval:1.0?target:self?selector:@selector(timer:)?userInfo:nil?repeats:YES];

[[NSRunLoop?currentRunLoop]?addTimer:timer?forMode:NSRunLoopCommonModes];

?

ios開發經常用到的延遲調用的方法,其實就是在當前線程的run loop上注冊timer來實現定時運行的。所以如果是在非主線程上使用,一定要有一個run loop。

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray?*)modes;

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

?

四、關于CADisplaylink相關知識

注意:
嚴格意義上講 CADisplayLink 并不是計時器控件, 它是與顯示器刷新頻率一致的。比如顯示的刷新頻率是60赫茲, 那么 CADisplayLink 就會每秒鐘執行60次。正是因為這個原因所以有時也把 CADisplayLink 當做計時器控件來使用。CADisplayLink:每次屏幕刷新的時候就會調用,屏幕一般一秒刷新60次。

//CADisplayLink應用舉例

CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timerAction)];

[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];??//?添加主運行循環

- (void)timerAction

{?// 注意:這個方法并不會馬上調用drawRect,其實這個方法只是給當前控件添加刷新的標記,等下一次屏幕刷新的時候才會調用drawRect

? ? [self setNeedsDisplay];

}

//如果想把一些文字/圖片等繪制在自定義的WZView上,必須在drawRect里寫代碼

- (void)drawRect:(CGRect)rect {

? ? // 如果以后想繪制東西到view上面,必須在drawRect方法里面,不管有沒有手動獲取到上下文

? ? UIImage *image =? [UIImage imageNamed:@"雪花"];

? ? [image drawAtPoint:CGPointMake(50, _snowY)];

}

?

五、NSTimer 和CADisplaylink的區別:

1.?如果在繪圖的時候需要用到定時器,通常CADisplaylink,?NSTimer很少用于繪圖,因為調度優先級比較低,并不會準時調用。

2. 使用繪圖產生動畫時,一般用CADisplaylink定時器在@selector(timerAction:)方法里調用[self?setNeedsDisplay];方法,因為CADisplaylink是在屏幕刷新時調用一次timerAction:方法,而setNeedsDisplay方法也是在屏幕刷新時調用drawRect方法重繪圖形,二者剛好同步。這樣產生的動畫就非常流暢,不會有卡頓的感覺。

?

?

文章系作者原創,轉載請注明出處:http://www.cnblogs.com/stevenwuzheng/p/5213908.html

如有錯誤,歡迎隨時指正!

?

?

?

?

轉載于:https://www.cnblogs.com/stevenwuzheng/p/5213908.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375051.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375051.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375051.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

靶場練習第十一天~vulnhub靶場之dc-3

一、準備工作 1.靶場鏈接: 百度網盤 請輸入提取碼 提取碼: 48d3 2.啟動靶場后會遇到如下情況: 2-1具體解決辦法如下: 啟動成功 3.查看kali的ip:ifconfig 二、信息收集 1.nmap的信息收集 (1)尋找靶機的ip&#xf…

UNIX環境高級編程一書中apue.h找不到

apue.h是作者為了方便自己寫的一個庫,在http://www.apuebook.com選擇你對應書中的source code,然后解壓壓縮包中在/include/apue.h以及/lib/error.c復制到你文件系統中/usr/include中即可。另外在apue.h中#include "error.c"即可。這樣gcc編譯…

大齡程序員怎樣渡過中年危機?(轉)

大齡程序員怎樣渡過中年危機? 作者前言: 話說再有十幾天就進入2016年了,想到這,我不由得五味雜陳。2016年對我來說是一個特殊的年份,因為我即將40歲了,人生正式告別青年期,進入中年了。 在娛樂圈…

靶場練習第十二天~vulnhub靶場之dc-4

一、準備工作 1.靶機下載鏈接 鏈接: 百度網盤 請輸入提取碼 提取碼: 3hq4 2.用ifconfig查看kali的ip 二、信息收集 1.nmap的信息收集 (1)主機發現 命令:nmap 192.168.101.0/24 (2)掃描靶機詳細信息 發現主機 192…

網絡命令-nc(二)

繼續Netcat 這個命令吧 1&#xff1a;遠程拷貝文件 在本地輸出 文件debian.img 到 192.168.5.40 主機12345端口監聽 nc -v 192.168.5.40 12345 < debian.img 在192.168.5.40 主機12345端口監聽&#xff0c;將文件指定為debian-copy.img nc -l -v 12345 > debian-copy.im…

靶場練習第十三天~vulnhub靶場之dc-5

一、準備工作 1.靶機環境搭建 下載鏈接: https://pan.baidu.com/s/1csvuJ_NVCBvVr75KhxyM3Q?pwdxie7 提取碼: xie7 2.kali的ip 命令&#xff1a;ifconfig 3.kali和靶機的都設置為NAT模式 二、信息收集 1.nmap的信息收集 &#xff08;1&#xff09;尋找靶機的ip 命令&…

Ubuntu中輸入輸出重定向及管道技術簡述

輸出 1、標準輸出 定義&#xff1a;程序在默認情況下輸出結果的地方&#xff08;stdout&#xff09;。 2、輸出重定向 定義&#xff1a;用于把數據的輸出轉移到另一個地方去。 3、Ubuntu中例子 $ls > ~/ls_out ##不顯示在顯示器上而是輸入到文件ls_out中 uname -r > ls_…

activex打包

http://www.cnblogs.com/weiwin/p/4493835.html activeX 打包 原文 http://www.docin.com/p-409284488.html CAB打包文檔說明 文檔目的本文檔的目的在于說明將ocx和dll以及相關的文件打包成一個CAB包&#xff0c;以便在網頁下調用ocx控件時免去手工將dll和其他一下文件拷貝到客…

靶場練習第十四天~vulnhub靶場之dc-6

一、準備工作 kali和靶機都選擇NAT模式&#xff08;kali與靶機同網段&#xff09; 1.靶場環境 下載鏈接: 百度網盤 請輸入提取碼 提取碼: bazx 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip 命令&#xff1a;sudo arp-scan -l 二、信息收集 1.nmap的信息收集 &#…

最短路徑Dijkstra算法和Floyd算法整理、

轉載自&#xff1a;http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路徑—Dijkstra算法和Floyd算法 Dijkstra算法 1.定義概覽 Dijkstra(迪杰斯特拉)算法是典型的單源最短路徑算法&#xff0c;用于計算一個節點到其他所有節點的最短路徑。主要特點是以…

Java Script 中 ==(Equal) 和 === (Identity Equal) 的區別和比較算法邏輯

判斷兩個變量是否相等在任何編程語言中都是非常重要的功能。 JavaScript 提供了 和 兩種判斷兩個變量是否相等的運算符&#xff0c;但我們開始學習的時候 JavaScript 的時候&#xff0c;就被一遍又一遍的告知&#xff1a; 要求變量的類型和值均相等&#xff0c;才能返回true…

靶場練習第十五天~vulnhub靶場之dc-7

一、準備工作 kali和靶機都選擇NAT模式&#xff08;kali與靶機同網段&#xff09; 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-7.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 &#xff08;1&…

ubuntu系統下如何修改host

Ubuntu系統的Hosts只需修改/etc/hosts文件&#xff0c;在目錄中還有一個hosts.conf文件&#xff0c;剛開始還以為只需要修改這個就可以了&#xff0c;結果發現是需要修改hosts。修改完之后要重啟網絡。具體過程如下&#xff1a;1、修改hostssudo gedit /etc/hosts2、添加解析記…

Matplotlib不顯示圖形

安裝好了Matplotlib&#xff0c;使用官方一個例子測試運行時&#xff0c;發現使用畫圖功能時&#xff0c;運行腳本老是顯示不出圖像&#xff0c;Google了一下&#xff0c;后來發現是matplotlibrc文件沒配置好。 參考了官方文檔&#xff0c;修改步驟如下 1.查找matplotlibrc文件…

靶場練習第十六天~vulnhub靶場之dc-8

一、準備工作 kali和靶機都選擇NAT模式&#xff08;kali與靶機同網段&#xff09; 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-8.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 &#xff08;1&…

【SpringMVC】SpringMVC系列4之@RequestParam 映射請求參數值

4、RequestParam 映射請求參數值 4.1、概述 Spring MVC 通過分析處理方法的簽名&#xff0c;將 HTTP 請求信息綁定到處理方法的相應人參中。Spring MVC 對控制器處理方法簽名的限制是很寬松的&#xff0c;幾乎可以按喜歡的任何方式對方法進行簽名。必要時可以對方法及方法入…

Sprint3

進展&#xff1a;今天主要是各自熟悉安卓應用開發平臺&#xff0c;設計了圖標&#xff0c;沒什么實際上的進展。 燃盡圖&#xff1a; 團隊工作照&#xff1a; 轉載于:https://www.cnblogs.com/XJXYJ/p/4495810.html

靶場練習第十七天~vulnhub靶場之dc-9

一、準備工作 kali和靶機都選擇NAT模式&#xff08;kali與靶機同網段&#xff09; 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-9.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 &#xff08;1&am…

Linux內核分析 02

二&#xff0c;操作系統是如何工作的 1、函數調用堆棧 三大法寶&#xff1a;存儲程序計算機 函數調用堆棧 中斷機制 堆棧&#xff1a;是C語言程序運行時必須的一個記錄調用路徑和參數的空間。是計算機內部現成的東西&#xff0c;我們直接使用。 包括函數調用框架、傳遞參數、保…

一 UI基本的用法

1. UIView的基本用法 //打印屏幕的寬和高CGRect screenBounds [[UIScreen mainScreen] bounds];NSLog("%f, %f", screenBounds.size.width, screenBounds.size.height);//創建一個UIView//UIView表示一個矩形區域UIView *v1 [[UIView alloc] init];//1.確定大小CGR…