首页 > 其他 > 详细

高精度的Timer(Objetive C)

时间:2014-03-20 22:59:04      阅读:557      评论:0      收藏:0      [点我收藏+]
 

 

-、NSTimer定时精度

  在实现一个坚实系统剪贴板变化当程序中,发现使用NSTimer精度达不到要求,类似当问题可以在stackoverflow中找到,如下:

bubuko.com,布布扣

 

经过查询文档之后,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到这份文档,文档中不建议使用该定时器,除非特别需要。

High Precision Timers in iOS / OS X

 链接: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

高精度的Timer(Objetive C)

原文:http://www.cnblogs.com/mystackflow/p/3614741.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!