8

サービス内の少量のデータをチェックしたいので、デバイスがバックグラウンドに入ったときにタイマーを実行しています。アプリデリゲートのapplicationDidEnterBackgroundメソッドで次のコードを使用しています

    UIApplication *app = [UIApplication sharedApplication];

//create new uiBackgroundTask
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

//and create new timer with async call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //run function methodRunAfterBackground
    NSString *server = [variableStore sharedGlobalData].server;
    NSLog(@"%@",server);
    if([server isEqual:@"_DEV"]){
        arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES];
    }
    else {
        arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES];
    }
    [[NSRunLoop currentRunLoop] addTimer:arrivalsTimer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
});

これは、デバイスが自動ロックされてからタイマーが停止するまで、まったく問題なく機能します。これが起こらないようにする方法について何か提案はありますか? デフォルトのライブ時間は 5 分であるため、ほとんどのデバイスはこれが 1 回刻みになるずっと前にロックされます。

ありがとう

4

1 に答える 1

4

いくつかの観察:

  1. H 氏が指摘するように、beginBackgroundTaskWithExpirationHandler現在の iOS バージョンでは 30 秒 (以前は 3 分) しか与えられません。したがって、5 分でタイマーを起動しようとしてもうまくいきません。

    [[UIApplication sharedApplication] backgroundTimeRemaining]残り時間を照会するために使用できます。

  2. デバイスがロックされると、バックグラウンド タスクが続行されます。アプリの終了は表示されません。ユーザーが「ホームボタンをダブルタップしてタスクスイッチャー画面を上にスワイプ」してアプリを手動で終了すると、バックグラウンドタスクが強制終了されますが、デバイスがロックされるだけではありません。

  3. タイマーに関するいくつかのコメント:

    • コードはタイマーをバックグラウンド キューに追加しています。それは一般的に必要ありません。アプリがバックグラウンド状態にあるという理由だけで、タイマーなどのメインの実行ループを引き続き使用できます。

      したがって、scheduledTimerWithTimeIntervalメインスレッドから呼び出すだけで完了です。絶対に必要な場合を除き、実行ループで GCD ワーカー スレッドを使い果たしても意味がありません (その場合でも、独自のスレッドを作成してそれに実行ループを追加する可能性があります)。

      ところで、何らかのバックグラウンド ディスパッチ キューでタイマーをスケジュールすることが絶対に必要な場合は、代わりにディスパッチ タイマーを使用する方がおそらく簡単です。実行ループの要件が完全になくなります。

    • scheduledTimerWithTimeIntervalところで、 で使用するのは適切ではありませんaddTimer。呼び出しscheduledTimerWithTimeIntervalてタイマーを作成し、それを現在の実行ループに追加します。別の実行ループに追加する場合は、使用timerWithTimeIntervalしてから呼び出します。addTimer

于 2015-05-15T16:33:01.880 に答える