第九歌 计时器(BEEPEOdyssey1)

图片 1图片 2

很详细的计时器小说 介绍了两种定时器方法
http://www.jianshu.com/p/c167ca4d1e7e

 1 *-------------------------------------
 2     BEEPER1.C -- Timer Demo Program No.1
 3     (c) Charles Petzold, 1998
 4     -------------------------------------*/
 5 
 6 #include <Windows.h>
 7 
 8 #define ID_TIMER 1
 9 
10     LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
11 
12 int WINAPI WinMain( __in HINSTANCE hInstance
13     , __in_opt HINSTANCE hPrevInstance
14     , __in LPSTR lpCmdLine
15     , __in int nShowCmd )
16 {
17     static TCHAR szAppName[] = TEXT("Bepper1");
18     HWND hwnd;
19     MSG msg;
20     WNDCLASS wndclass;
21 
22     wndclass.style = CS_HREDRAW | CS_VREDRAW;
23     wndclass.lpfnWndProc = WndProc;
24     wndclass.cbClsExtra = 0;
25     wndclass.cbWndExtra = 0;
26     wndclass.hInstance = hInstance;
27     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
28     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
29     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
30     wndclass.lpszMenuName = NULL;
31     wndclass.lpszClassName = szAppName;
32 
33     if (!RegisterClass(&wndclass))
34     {
35         MessageBox(NULL, TEXT("Program requires Windows NT!")
36             , szAppName, MB_ICONERROR);
37         return 0;
38     }
39 
40     hwnd = CreateWindow(szAppName, TEXT("Beeper1 Timer Demo")
41         , WS_OVERLAPPEDWINDOW
42         , CW_USEDEFAULT, CW_USEDEFAULT
43         , CW_USEDEFAULT, CW_USEDEFAULT
44         , NULL, NULL, hInstance, NULL);
45 
46     ShowWindow(hwnd, nShowCmd);
47     UpdateWindow(hwnd);
48 
49     while (GetMessage(&msg, NULL, 0, 0))
50     {
51         TranslateMessage(&msg);
52         DispatchMessage(&msg);
53     }
54 
55     return msg.wParam;
56 }
57 
58 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
59 {
60     static BOOL fFlipFlop = FALSE;
61     HBRUSH hBrush;
62     HDC hdc;
63     PAINTSTRUCT ps;
64     RECT rc;
65 
66     switch (message)
67     {
68     case WM_CREATE:
69         SetTimer(hwnd, ID_TIMER, 1000, NULL);
70         return 0;
71 
72     case WM_TIMER:
73         MessageBeep(-1);
74         fFlipFlop = !fFlipFlop;
75         InvalidateRect(hwnd, NULL, FALSE);
76         return 0;
77 
78     case WM_PAINT:
79         hdc = BeginPaint(hwnd, &ps);
80 
81         GetClientRect(hwnd, &rc);
82         hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));
83         FillRect(hdc, &rc, hBrush);
84 
85         EndPaint(hwnd, &ps);
86         DeleteObject(hBrush);
87         return 0;
88 
89     case WM_DESTROY:
90         KillTimer(hwnd, ID_TIMER);
91         PostQuitMessage(0);
92         return 0;
93     }
94 
95     return DefWindowProc(hwnd, message, wParam, lParam);
96 }
  • NSTimer
    务必投入Runloop、
    存在延迟、
    UIScrollView滑动会暂停计时(若不想被UIScrollView滑动影响,须要将
    timer 添加再到 UITrackingRunLoopMode 或
    直接助长到NSRunLoopCommonModes 中)
  • GCD计时器 精度最好 ✨
  • CADisplayLink
    刷新频率固定 (取决CPU的无暇程度)、
    显示屏刷新时调用
    (CADisplayLink在健康情况下会在每一次刷新实现都被调用,精确度很是高。但一旦调用的格局相比耗时,超越了显示屏刷新周期,就会导致跳过若干次回调调用机会)、
    符合做界面渲染(CADisplayLink能够确定保证系统渲染每一帧的时候大家的章程都被调用,从而确认保障了动画的流畅性。)

BEEPER1.C

后台常驻 的题材 看到了一篇文章
https://www.cnblogs.com/lyanet/archive/2013/03/26/2983079.html
还有另一篇
http://www.jianshu.com/p/d1ecc467faff
透过那五个
苹果文书档案说到别的利用都有3分钟的后台执行职务的年月
。。。跟苹果借点时间用用。。。不用配置info.plist
制止因为布署后台长期运维后,苹果审查出您滥用api(借使你安顿了
项目中必须求有连带的机能)

第贰篇涉嫌了 应该在长期职分实现后,大家需求做一些工作举办清理:

 

  1. 终止全数的线程和定时器,不管他们是基础定时器照旧GCD中开创的。

  2. 调用UIApplication的endBackgroundTask:方法来终止后台任务。

  3. 将职务标识设置为UIBackgroundTaskInvalid,标志我们的天职实现。

终极,当我们的应用回到前台,就算我们的后台任务还在履行中,我们供给确定保障我们在杀死它:

首要代码放在下面以免丢失

  • 3分钟的后台执行义务

@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;


- (void)applicationDidEnterBackground:(UIApplication *)application {

    UIApplication*   app = [UIApplication sharedApplication];

    __weak typeof(self)weakSelf = self;

    self.backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{            if (weakSelf.backgroundTaskIdentifier != UIBackgroundTaskInvalid)
        {
            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
        }
        });
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{            if (weakSelf.backgroundTaskIdentifier != UIBackgroundTaskInvalid)
        {
            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
        }
        });
    });
}


- (void)applicationWillEnterForeground:(UIApplication *)application {

    if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){

        [self endBackgroundTask];

    }

}
- (void) endBackgroundTask{

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    __weak typeof(self)weakSelf = self;

    dispatch_async(mainQueue, ^(void) {

        if (weakSelf != nil){

            [[UIApplication sharedApplication] endBackgroundTask:weakSelf.backgroundTaskIdentifier];

            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;

        }

    });

}

#pragma mark - 定时器(GCD)
- (void)creatTimer{

    //设置倒计时时间
    //__block 如果修饰指针时,指针相当于弱引用,指针对指向的对象不产生引用计数的影响
    //通过检验发现,方法调用后,timeout会先自动-1,所以如果从30秒开始倒计时timeout应该写31
    __block int timeOut = 31;

    //获取全局队列
    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //创建一个定时器,并将定时器的任务交给全局队列执行(并行,不会造成主线程阻塞)
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, global);

    //设置触发的间隔时间
//    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);

    dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0); //每秒执行

    //1.0 * NSEC_PER_SEC  代表设置定时器触发的时间间隔为1s
    //0 * NSEC_PER_SEC    代表时间允许的误差是 0s

    //block内部 如果对当前对象的强引用属性修改,应该使用 __weak typeof(self)weakSelf 修饰 避免循环引用
    __weak typeof(self)weakSelf = self;

    //设置定时器触发事件
    dispatch_source_set_event_handler(timer, ^{

        //倒计时 刷新UI,当倒计时为0时,结束倒计时

        //1.每调用一次 时间-1
        timeOut --;

        //2.对timeOut 进行判断时间是停止倒计时 还是修改UI
        if (timeOut <= 0) {

            //停止倒计时时

            //关闭定时器
            dispatch_source_cancel(timer);

            //主线程更新UI
            dispatch_async(dispatch_get_main_queue(), ^{


            });

        }else{
            //主线程更新UI
            dispatch_async(dispatch_get_main_queue(), ^{


            });
        }

    });

    dispatch_resume(timer);

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图