アプリがバックグラウンドにあるとき、人々はスケジュールされたNSTimerにどのように対処しますか?
アプリで何かを1時間ごとに更新するとします。
updateTimer = [NSTimer scheduledTimerWithTimeInterval:60.0*60.0
target:self
selector:@selector(updateStuff)
userInfo:nil
repeats:YES];
バックグラウンドでは、このタイマーは明らかに起動しません(?)。ユーザーがアプリに戻ったらどうなりますか?同じ時間で、タイマーはまだ実行されていますか?
そして、ユーザーが1時間以上戻ってきたらどうなるでしょう。見逃したすべての時間にトリガーされるのか、それとも次の更新時間まで待機するのか?
起動するはずの日付が過去の場合、アプリがフォアグラウンドに入った直後に更新することを望みます。それは可能ですか?
バックグラウンドでコードを実行することは許可されていないため、タイマーを設定してこの問題を解決しないでください。ユーザーがその間にiPhoneを再起動した場合、または他のEdgeの場合にどうなるかを想像してください。
使用 applicationDidEnterBackground:
およびapplicationWillEnterForeground:
必要な動作を取得するAppDelegateのメソッド。再起動やメモリ不足のためにアプリが完全に終了した場合にも機能するため、より堅牢です。
アプリがバックグラウンドに移行するときにタイマーが次に起動する時間を節約し、アプリがフォアグラウンドに戻ったときにアクションを実行する必要があるかどうかを確認できます。また、このメソッドでタイマーを停止および開始します。アプリの実行中に、タイマーを使用して適切なタイミングで更新をトリガーできます。
can バックグラウンド実行モードでタイマーを起動します。いくつかのトリックがあります:
beginBackgroundTaskWithExpirationHandler
を使用してバックグラウンド実行を選択する必要があります。[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]
メインスレッドを使用している場合:
{
// 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
}
注
あなたまたは他の誰かが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()
}
乾杯!
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分後、タイマーはそれ以上起動しなくなり、アプリがフォアグラウンドで復帰すると、再び起動し始めます
現在の実行ループにタイマーを追加する必要があります。
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes];
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes];
実行ループにタイマーを追加する必要があります( 参照 -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で動作するバックグラウンドの許可(必要なバックグラウンドモード)を追加する必要があります。
============== 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];
ここでは、アプリがバックグラウンドになったときでもこれが機能します。新しい問題が見つかった場合は私に尋ねてください。
グローバル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];
ここでは、アプリがバックグラウンドになったときでもこれが機能します。新しい問題が見つかった場合は私に尋ねてください。