我的应用从外围设备通过BLE下载了一堆数据。如果我锁定屏幕,我的应用程序将移动到后台并启动后台任务。下载完成,但如果处理(由于它是大量数据需要相当长的时间)开始应用程序崩溃,因为它无法连接到数据库。
我想在此时停止执行并等待应用程序再次变为活动状态,但不知怎的,我无法实现此目的。我想我需要某种信号量来等待应用程序变为活动状态。
到目前为止我的代码:
- (void)viewDidLoad
{
//Some other code
//initialize flag
isInBackgroud = NO;
// check if app is in the background
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
// check if app is in the foreground
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterForeground) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)appDidEnterBackground {
NSLog(@"appDidEnterBackground");
isInBackground = YES;
UIApplication *app = [UIApplication sharedApplication];
NSLog(@"remaining Time: %f", [app backgroundTimeRemaining]);
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"expirationHandler");
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
}
- (void)appDidEnterForeground {
NSLog(@"appDidEnterForeground");
isInBackground = NO;
if (bgTask != UIBackgroundTaskInvalid) {
UIApplication *app = [UIApplication sharedApplication];
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}
//BLE connection and reading data via notification
//when finished [self processData] is called.
- (void)processData {
if (isInBackground) {
//set reminder
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate date];
localNotification.alertBody = [NSString stringWithFormat:@"Data was downloaded, return to the application to proceed processing your data."];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
UIApplication *app = [UIApplication sharedApplication];
//end background task
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
//wait for application to become active again
while (isInBackground) {
NSLog(@"isInBackground");
NSLog(@"remaining Time: %f", [app backgroundTimeRemaining]);
sleep(1);
}
//process data
}
所以我注意到,如果我调用[app endBackgroundTask:bgTask];
应用程序只是继续运行但是当我想要连接到我的数据库时崩溃。这就是我添加while(isInBackground)
循环的原因。我知道这不是一个好习惯,因为它在注意时会积极地浪费CPU时间。我应该在那时使用信号量,但我不知道该怎么做。
因为我在那个循环中积极地畏缩,所以永远不会调用appDidEnterForegronund
并且循环会永远运行。
答案 0 :(得分:3)
您不应该进行循环,因为您的应用只有在iOS被其停止之前才能处理这么长时间。相反,当您的应用进入后台时,请设置一个状态变量,使其在后台运行。对前景做同样的事。
如果您处于前台,则仅更新数据库,否则,设置一个状态变量,告知您的应用已完成下载,但仍需要处理数据。如果需要,请存储数据。
然后,当您的应用重新启动时,请检查该变量的状态并进行处理。
而不是坐在循环中等待某个状态改变,设置变量,并使用事件驱动的编程。