-、NSTimer定时精度
在实现一个坚实系统剪贴板变化当程序中,发现使用NSTimer精度达不到要求,类似当问题可以在stackoverflow中找到,如下:
经过查询文档之后,timer当触发是在runloop当循环中检查是否已经到达触发条件,如果没有到达,就在下一次循环中继续检查。因此NSTimer当精度受制与Runloop的循环时间,并且收到线程调度的影响,文档中说明是50~100ms,对于一般的应用可以满足。
二、更精确的Timer
在stackoverflow上面搜索如何获得更精确的timer之后,发现下面这种方式能解决一般问题,但是精度还是大于200ms,但是比NSTimer更稳定一些,当程序退到后台之后,仍旧能正常触发。
解决办法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
//建立新线程 [ NSThread
detachNewThreadSelector: @selector (timer) toTarget: self
withObject: nil ]; //make a new thread //在线程中使用 NSdate 进行判断 - ( void )timer { @autoreleasepool
{ NSDate
*startDate = [ NSDate
date]; while
( YES ) { usleep(10000); if ([[ NSDate
date] timeIntervalSinceDate:startDate] >= watch_interval) { startDate = [ NSDate
date]; objc_msgSend( self , @selector (watchLoop), nil ); } } } } |
这个方法仍然有弊端,可能是NSDate到更新间隔,导致200ms到间隔不能缩小。
三、更精确到定时器,如果想获得更精确到定时器,可以参考apple到这份文档,文档中不建议使用该定时器,除非特别需要。
链接:https://developer.apple.com/library/ios/technotes/tn2169/_index.html
四、监视定时器变化到代码
.h 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 |
// // PastboardWatcher.h // PastboardWatcher // // Created by on 14-3-20. // Copyright (c) 2014年 master. All rights reserved. // #import <Foundation/Foundation.h> @protocol
PastboardWatcherDelegate; @interface
PastboardWatcher : NSObject + ( id )shanreInstance; - ( void )registerObsever:( id <PastboardWatcherDelegate>)delegate; - ( void )removeDelegate:( id <PastboardWatcherDelegate>)delegate; @end @protocol
PastboardWatcherDelegate < NSObject > - ( void )generalPastboardDidChange; @end |
.m文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 |
// // PastboardWatcher.m // PastboardWatcher // // Created by on 14-3-20. // Copyright (c) 2014年 master. All rights reserved. // #import <objc/message.h> #import "PastboardWatcher.h" static
const
NSTimeInterval
watch_interval = 0.2; @interface
PastboardWatcher () @property
( nonatomic , strong) NSMutableArray
*obseverArray; @property
( nonatomic , assign) NSInteger
changeCount; @property
( nonatomic , strong) NSRecursiveLock
*lock; @end @implementation
PastboardWatcher + ( id )shanreInstance { static
PastboardWatcher *instance = nil ; static
dispatch_once_t once_token; dispatch_once(&once_token,^{ instance = [[PastboardWatcher alloc] init]; }); return
instance; } - ( id )init { if ( self
= [ super
init]) { _obseverArray = [[ NSMutableArray
alloc] init]; _changeCount = [[ NSPasteboard
generalPasteboard] changeCount]; _lock = [[ NSRecursiveLock
alloc] init]; [ NSThread
detachNewThreadSelector: @selector (timer) toTarget: self
withObject: nil ]; //make a new thread } return
self ; } - ( void )registerObsever:( id <PastboardWatcherDelegate>)delegate { [_lock lock]; [_obseverArray addObject:delegate]; [_lock unlock]; } - ( void )removeDelegate:( id <PastboardWatcherDelegate>)delegate { [_lock lock]; NSInteger
findIndex = [_obseverArray indexOfObject:delegate]; if (findIndex != NSNotFound ) [_obseverArray removeObjectAtIndex:findIndex]; [_lock unlock]; } - ( void )timer { @autoreleasepool
{ NSDate
*startDate = [ NSDate
date]; while
( YES ) { usleep(10000); if ([[ NSDate
date] timeIntervalSinceDate:startDate] >= watch_interval) { startDate = [ NSDate
date]; objc_msgSend( self , @selector (watchLoop), nil ); } } } } - ( void )watchLoop { NSInteger
current_changeCount = [ NSPasteboard
generalPasteboard].changeCount; if (current_changeCount != _changeCount) { _changeCount = current_changeCount; objc_msgSend( self , @selector (notifyObseverChange), nil ); } } - ( void )notifyObseverChange { [_lock lock]; NSArray
*tempArray = [_obseverArray copy ]; [_lock unlock]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ for
( id <PastboardWatcherDelegate> delegate in tempArray) { if ([delegate respondsToSelector: @selector (generalPastboardDidChange)]) { objc_msgSend(delegate, @selector (generalPastboardDidChange)); } } }); } @end |
高精度的Timer(Objetive C),布布扣,bubuko.com
原文:http://www.cnblogs.com/mystackflow/p/3614741.html