利用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);
}
});
}