我有一个关于后台任务让我困惑几天的问题。为了使描述简单,我将我的项目分成了这个实验。
#import "ViewController.h"
@interface ViewController () {
UIBackgroundTaskIdentifier background;
NSTimer *t;
}
- (void)beginBackgroundTask;
- (void)endBackgroundTask;
- (void)printIt;
- (IBAction)startBGTaskPressed:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
t = nil;
background = UIBackgroundTaskInvalid;
[self beginBackgroundTask];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Internal use
- (void)beginBackgroundTask {
NSLog(@"%s", __PRETTY_FUNCTION__);
UIApplication *app = [UIApplication sharedApplication];
background = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"%s", __PRETTY_FUNCTION__);
[self endBackgroundTask];
}];
NSLog(@"background created: %d", background);
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
t = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(printIt)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:t
forMode:NSRunLoopCommonModes]; // NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] run];
});
}
- (void)endBackgroundTask {
NSLog(@"Ending background: %d", background);
if (t!=nil) {
[t invalidate];
t = nil;
}
[[UIApplication sharedApplication] endBackgroundTask:background];
background = UIBackgroundTaskInvalid;
}
- (void)printIt {
NSLog(@"%s", __PRETTY_FUNCTION__);
NSLog(@"remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);
}
#pragma mark - Actions
- (IBAction)startBGTaskPressed:(id)sender {
if (background==UIBackgroundTaskInvalid) {
NSLog(@"background not ready --> create");
[self beginBackgroundTask];
}
else {
NSLog(@"background ready --> return");
}
}
@end
简短说明:在- (void)viewDidLoad
中,我按- (void)beginBackgroundTask
创建后台任务。当应用程序进入后台后,当后台任务过期(3分钟,但在某些文档中提到10分钟)时,会执行- (void)endBackgroundTask
,其中清除计时器并结束后台任务。
但是当我在XCode调试中暂停程序执行时,我从Xcode看到的很奇怪,我看到了:
Thread 3
Queue: com.apple.root.default-priority
0 mach_msg_trap
7 -[NSRunLoop(NSRunLoop) run]
8 __37-[ViewController beginBackgroundTask]_block_invoke14
9 _dispatch_call_block_and_release
12 _pthread_wqthread
据我所知,8 __37-[ViewController beginBackgroundTask]_block_invoke14
是beginBackgroundTaskWithExpirationHandler
中- (void)beginBackgroundTask
的阻止。但为什么Xcode仍显示7 -[NSRunLoop(NSRunLoop) run]
?
我在- (void)endBackgroundTask
做错了吗? Xcode不会在此功能中警告我。
我们如何确保后台任务成功结束? Xcode Instruments可以提供帮助吗?
感谢任何回复。