天天看点

如何让你的应用在后台可以继续处理未完事务

利用GCD线程技术,加入MainDispatchQueue队列,它会将任务插入主线程的RunLoop当中去执行,所以显然是个串行队列,我们可以使用它来更新UI。关键是app切换到后台它还在正常运行。不过它运行的时间不是无限的,是在后台存活3分钟(这个是app独立运行的情况下是后台存活三分钟,在Xcode运行应用连接真机调试这个线程一直活着。)。当然你重新切换到前台时这个线程就又活了。由于它已经在主线程了,不能使用dispatch_sync(dispatch_get_main_queue(), ^{回主线程刷线UI否则崩溃。就是这种起线程的方式只能刷新一次UI。

下面是一个测试GCD线程使用MainDispatchQueue证明它在后台能正常运行的代码,做一个单例或页面,在代码中调用test函数,可以看到,它在后台还照常打日志。这个加入主线程的函数调用时,由于它一直独占cpu并且由于程序再sleep所以无法刷新UI,所以点击按钮无效。看来它的使用是很有局限性的:

//测试加入GCD的MainDispatchQueue队列里的线程在后台仍旧可以运行三分钟
-(void)test
{
    FLDDLogDebug(@"测试加入GCD的MainDispatchQueue队列线程在后台仍旧可以运行");
    dispatch_async(dispatch_get_main_queue(), ^{
        for(NSInteger i = 0; ; i++)
        {
            sleep(1);
            FLDDLogDebug(@"test:%ld", (long)i);
        }
    });
}      

它能解决应用切换到后台,NSTimer无法实时计时的问题。再也不用通过几个变量记录时间,切换到前台再刷新时间显示了。

下面是记录app在后台存活时间的部分日志:

2018/12/19 10:45:53:537  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:12
2018/12/19 10:45:54:538  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:13

2018/12/19 10:48:55:352  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:193
2018/12/19 10:48:56:358  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:194
2018/12/19 10:48:57:363  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:195
2018/12/19 10:48:58:369  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:196
2018/12/19 10:48:59:374  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:197
2018/12/19 10:49:00:380  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:198
2018/12/19 10:49:01:384  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:199
2018/12/19 10:49:02:390  ViewController.m:-[ViewController test]_block_invoke:31 Debug:test:200      
-(void)test
{
    FLDDLogDebug(@"测试加入GCD的MainDispatchQueue队列线程在后台仍旧可以运行");
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(NSInteger i = 0; ; i++)
        {
            sleep(1);
            FLDDLogDebug(@"test:%ld", (long)i);
        }
    });
}      

继续阅读