【问题标题】:End background task and wait until app becomes active again - BLE processing data结束后台任务并等待应用再次激活 - BLE 处理数据
【发布时间】:2015-02-06 13:32:02
【问题描述】:

我的应用通过 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 objective-c cocoa-touch semaphore


    【解决方案1】:

    您不应该循环,因为您的应用在被 iOS 停止之前只有很长时间才能处理。相反,当您的应用程序进入后台时,请设置它在后台的状态变量。对前景执行相同操作。

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

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

    与其坐在循环中等待某些状态发生变化,不如设置变量并使用事件驱动编程。

    【讨论】:

    • Thakns,不知何故我没有看到这个:P
    猜你喜欢
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    相关资源
    最近更新 更多