web-dev-qa-db-ja.com

アプリがバックグラウンドにあるときにスケジュールされたNSTimer?

アプリがバックグラウンドにあるとき、人々はスケジュールされたNSTimerにどのように対処しますか?

アプリで何かを1時間ごとに更新するとします。

updateTimer = [NSTimer scheduledTimerWithTimeInterval:60.0*60.0 
target:self 
selector:@selector(updateStuff) 
userInfo:nil 
repeats:YES];

バックグラウンドでは、このタイマーは明らかに起動しません(?)。ユーザーがアプリに戻ったらどうなりますか?同じ時間で、タイマーはまだ実行されていますか?

そして、ユーザーが1時間以上戻ってきたらどうなるでしょう。見逃したすべての時間にトリガーされるのか、それとも次の更新時間まで待機するのか?

起動するはずの日付が過去の場合、アプリがフォアグラウンドに入った直後に更新することを望みます。それは可能ですか?

50
cannyboy

バックグラウンドでコードを実行することは許可されていないため、タイマーを設定してこの問題を解決しないでください。ユーザーがその間にiPhoneを再起動した場合、または他のEdgeの場合にどうなるかを想像してください。

使用 applicationDidEnterBackground:およびapplicationWillEnterForeground:必要な動作を取得するAppDelegateのメソッド。再起動やメモリ不足のためにアプリが完全に終了した場合にも機能するため、より堅牢です。

アプリがバックグラウンドに移行するときにタイマーが次に起動する時間を節約し、アプリがフォアグラウンドに戻ったときにアクションを実行する必要があるかどうかを確認できます。また、このメソッドでタイマーを停止および開始します。アプリの実行中に、タイマーを使用して適切なタイミングで更新をトリガーできます。

39
Mac_Cain13

can バックグラウンド実行モードでタイマーを起動します。いくつかのトリックがあります:

メインスレッドを使用している場合:

{
    // Declare the start of a background task
    // If you do not do this then the mainRunLoop will stop
    // firing when the application enters the background
    self.backgroundTaskIdentifier =
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
    }];

    // Make sure you end the background task when you no longer need background execution:
    // [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];

    [NSTimer scheduledTimerWithTimeInterval:0.5
                                     target:self
                                   selector:@selector(timerDidFire:)
                                   userInfo:nil
                                    repeats:YES];
}

- (void) timerDidFire:(NSTimer *)timer
{
    // This method might be called when the application is in the background.
    // Ensure you do not do anything that will trigger the GPU (e.g. animations)
    // See: http://developer.Apple.com/library/ios/DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//Apple_ref/doc/uid/TP40007072-CH4-SW47
}

  • アプリは、バックグラウンド実行で最大10分(iOS 7では約3分)しか取得できません。この後、タイマーは起動を停止します。
  • IOS 7の時点で、デバイスがlockedの場合、フォアグラウンドアプリはほぼ即座に一時停止します。 iOS 7アプリがロックされた後、タイマーは起動しません。
42
Robert

あなたまたは他の誰かがSwiftのバックグラウンドでNSTimerを実行する方法を探している場合、以下をApp Delegateに追加します:

var backgroundUpdateTask: UIBackgroundTaskIdentifier = 0


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    return true
}

func applicationWillResignActive(application: UIApplication) {
    self.backgroundUpdateTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
        self.endBackgroundUpdateTask()
    })
}

func endBackgroundUpdateTask() {
    UIApplication.sharedApplication().endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskInvalid
}

func applicationWillEnterForeground(application: UIApplication) {
    self.endBackgroundUpdateTask()
}

乾杯!

17
gellieb

IOS 8では、アプリがバックグラウンドにある場合(iPhoneがロックされている場合でも)NSTimerを簡単な方法で最大3分まで動作させることができます。

必要に応じて、通常どおりscheduledTimerWithTimeInterval:target:selector:userInfo:repeats:メソッドを実装するだけです。 AppDelegate内でプロパティを作成します。

UIBackgroundTaskIdentifier backgroundUpdateTask

その後、appDelegateメソッドで:

- (void)applicationWillResignActive:(UIApplication *)application {
    self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    [self endBackgroundUpdateTask];
    }];
}

- (void) endBackgroundUpdateTask
{
    [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
    self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self endBackgroundUpdateTask];
}

3分後、タイマーはそれ以上起動しなくなり、アプリがフォアグラウンドで復帰すると、再び起動し始めます

6

バックグラウンドでは、このタイマーは明らかに起動しません

この投稿 は、それほど明確ではないことを示唆しています。アプリがバックグラウンドになったらタイマーを無効にし、フォアグラウンドに戻ったらタイマーを再起動する必要があります。バックグラウンドで何かを実行することは可能かもしれませんが、それでもあなたを殺してしまうかもしれません...

IOSマルチタスクアプローチに関する優れたドキュメントを見つけることができます こちら

6
jbat100

現在の実行ループにタイマーを追加する必要があります。

[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];
3
Maverick King
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
    loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes];
2
vualoaithu

実行ループにタイマーを追加する必要があります( 参照 -Apple開発者ページ)。

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:@selector(updateTimer)  userInfo:nil  repeats:true];

[[NSRunLoop mainRunLoop] addTimer: timer forMode:NSRunLoopCommonModes];

//funcation

-(void) updateTimer{
NSLog(@"Timer update");

}

infoPlistで動作するバックグラウンドの許可(必要なバックグラウンドモード)を追加する必要があります。

1

============== Objective Cの場合================

グローバルuibackgroundタスク識別子を作成します。

UIBackgroundTaskIdentifier bgRideTimerTask;

タイマーを作成してBGTaskIdentifierを追加します。これを使用して、新しいタイマーオブジェクトを作成するときに古いBGTaskIdentifierを削除することを忘れないでください。

 [timerForRideTime invalidate];
 timerForRideTime = nil;

 bgRideTimerTask = UIBackgroundTaskInvalid;

 UIApplication *sharedApp = [UIApplication sharedApplication];       
 bgRideTimerTask = [sharedApp beginBackgroundTaskWithExpirationHandler:^{

                            }];
 timerForRideTime =  [NSTimer scheduledTimerWithTimeInterval:1.0
                                                                                 target:self
                                                                               selector:@selector(timerTicked:)
                                                                               userInfo:nil
                                                                                repeats:YES]; 
                                                   [[NSRunLoop currentRunLoop]addTimer:timerForRideTime forMode: UITrackingRunLoopMode];

ここでは、アプリがバックグラウンドになったときでもこれが機能します。新しい問題が見つかった場合は私に尋ねてください。

0
NIRAV BHAVSAR

グローバルuibackgroundタスク識別子を作成します。

UIBackgroundTaskIdentifier bgRideTimerTask;

タイマーを作成してBGTaskIdentifierを追加します。これを使用して、新しいタイマーオブジェクトを作成するときに古いBGTaskIdentifierを削除することを忘れないでください。

 [timerForRideTime invalidate];
 timerForRideTime = nil;

 bgRideTimerTask = UIBackgroundTaskInvalid;

 UIApplication *sharedApp = [UIApplication sharedApplication];       
 bgRideTimerTask = [sharedApp beginBackgroundTaskWithExpirationHandler:^{

                            }];
 timerForRideTime =  [NSTimer scheduledTimerWithTimeInterval:1.0
                                                                                 target:self
                                                                               selector:@selector(timerTicked:)
                                                                               userInfo:nil
                                                                                repeats:YES]; 
                                                   [[NSRunLoop currentRunLoop]addTimer:timerForRideTime forMode: UITrackingRunLoopMode];

ここでは、アプリがバックグラウンドになったときでもこれが機能します。新しい問題が見つかった場合は私に尋ねてください。

0
NIRAV BHAVSAR