结束后台任务并等待应用程序再次变为活动状态 - BLE处理数据

时间:2015-02-06 13:32:02

标签: ios objective-c cocoa-touch semaphore

我的应用从外围设备通过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并且循环会永远运行。

1 个答案:

答案 0 :(得分:3)

您不应该进行循环,因为您的应用只有在iOS被其停止之前才能处理这么长时间。相反,当您的应用进入后台时,请设置一个状态变量,使其在后台运行。对前景做同样的事。

如果您处于前台,则仅更新数据库,否则,设置一个状态变量,告知您的应用已完成下载,但仍需要处理数据。如果需要,请存储数据。

然后,当您的应用重新启动时,请检查该变量的状态并进行处理。

而不是坐在循环中等待某个状态改变,设置变量,并使用事件驱动的编程。