结束后台任务并等待应用程序再次激活 - BLE 处理数据
End background task and wait until app becomes active again - BLE processing data
我的应用程序通过 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
永远不会被调用并且循环永远运行。
您不应该循环,因为您的应用在 iOS 停止之前只需要很长时间来处理。相反,当您的应用程序进入后台时,设置它在后台的状态变量。对前景做同样的事情。
仅当您在前台时才更新数据库,否则,请设置一个状态变量,告诉您的应用程序您已完成下载,但仍需要处理数据。如果需要,请存储数据。
然后,当您的应用重新启动时,检查该变量的状态并进行处理。
与其坐在循环中等待某些状态发生变化,不如设置变量并使用事件驱动编程。
我的应用程序通过 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
永远不会被调用并且循环永远运行。
您不应该循环,因为您的应用在 iOS 停止之前只需要很长时间来处理。相反,当您的应用程序进入后台时,设置它在后台的状态变量。对前景做同样的事情。
仅当您在前台时才更新数据库,否则,请设置一个状态变量,告诉您的应用程序您已完成下载,但仍需要处理数据。如果需要,请存储数据。
然后,当您的应用重新启动时,检查该变量的状态并进行处理。
与其坐在循环中等待某些状态发生变化,不如设置变量并使用事件驱动编程。