4

GCD タイマー ソースを使用するための Objective-C ラッパーを作成しています。目標の 1 つは、アプリケーションがバックグラウンドに入ったときに、ラッパーがタイマー ソースの一時停止を管理することです。

ドキュメントは、特にタイマーを無効にするために使用する必要があることを-[UIApplicationDelegate applicationDidEnterBackground:]示しています。dispatch_suspend()に応答してGCD タイマー ( ) を一時停止しているという点で、これをやや大まかに解釈しています (おそらくそれが私の問題の原因ですか? UIApplicationDidEnterBackgroundNotification)。

ラッパーのインスタンスが初期化[UIApplication sharedApplication].applicationState != UIApplicationStateBackgroundされると、初期化シーケンスの一部として GCD タイマー ソースを最初に再開する必要があるかどうかがチェックされます。また、タイマー ソースの一時停止と再開に使用する と (それぞれ) をUIApplicationDidEnterBackgroundNotification登録します。UIApplicationWillEnterForegroundNotification

私が観察した問題は[UIApplication sharedApplication].applicationState != UIApplicationStateBackground、タイマー ソースが再開されるように初期化中のチェックに合格した場合があるようであり、受信された次の通知UIApplicationWillEnterForegroundNotificationにより、タイマー ソースが 2 回目に再開されることです。これは、2 回目の再開時にタイマーが中断されなかったため、クラッシュにつながります。

アプリケーションの状態をローカルで追跡し、重複する遷移を確認することでこれを回避できますが、何か間違ったことを行っているか、(実装またはドキュメントに) バグがあるのではないかと心配しています。

4

3 に答える 3

2

アプリの状態は次のように機能します。

最初のローンチでは、

  1. アプリケーション:didFinishLaunchingWithOptions
  2. applicationDidBecomeActive

ホームボタンを押すと、

  1. applicationWillResignActive
  2. applicationDidEnterBackground

バックグラウンドアプリを開くと、

  1. applicationWillEnterForeground
  2. applicationDidBecomeActive

オープニング - (最初の起動とバックグラウンド アプリを開く) - applicationDidBecomeActive が呼び出されます - ここでタイマーを初期化します。

呼び出しの非表示または受信など - applicationWillResignActive が呼び出されます - ここでタイマーを停止します。

お役に立てれば。

于 2012-12-17T07:48:18.623 に答える
0

そのため、何が起こっているのかをよりよく理解するためにできることは次のとおりです。

アプリの main.m に、これを追加します。

 @interface GTTestObject : NSObject

 - (void)logNotification:(id)sender;
 @end

 @implementation GTTestObject

 - (void)logNotification:(id)sender {

     NSLog(@"%@", [(NSNotification *)sender name]);

 }
 @end


 int main(int argc, char *argv[])
 {
     @autoreleasepool {

         // I'm assuming you'd be using ARC...
         GTTestObject *obj = [[GTTestObject alloc] init];
         [[NSNotificationCenter defaultCenter] addObserver:obj selector:@selector(logNotification:) name:nil object:nil];

         return UIApplicationMain(argc, argv, nil, NSStringFromClass([GTAppDelegate class]));
     }
 }

次に、すべてのMyAppDelegate.mメソッドについて「...didFinishLaunching、...didEnterBackgroundなど」。これを追加:

     NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));

これで、シーケンス、タイムスタンプ、および (おそらく) 同時に発生した通知/デリゲート呼び出しとの競合を確認できます。

テストごとにわずかに異なる結果が得られる可能性があるため、確認するために数回実行してください。

実行例については、毎回これを確認します。

 2012-12-21 08:13:58.559 Gamerton[34158:c07] [GTAppDelegate application:didFinishLaunchingWithOptions:] state: UIApplicationStateInactive
 2012-12-21 08:13:58.560 Gamerton[34158:c07] UIApplicationDidFinishLaunchingNotification state: UIApplicationStateInactive

 ...

 2012-12-21 08:13:58.561 Gamerton[34158:c07] [GTAppDelegate applicationDidBecomeActive:] state: UIApplicationStateActive
 2012-12-21 08:13:58.561 Gamerton[34158:c07] UIApplicationDidBecomeActiveNotification state: UIApplicationStateActive

 ... Hit home button

 2012-12-21 08:16:08.227 Gamerton[34170:c07] [GTAppDelegate applicationWillResignActive:] state: UIApplicationStateActive
 2012-12-21 08:16:08.228 Gamerton[34170:c07] UIApplicationWillResignActiveNotification state: UIApplicationStateActive
 2012-12-21 08:16:08.229 Gamerton[34170:c07] UIApplicationSuspendedNotification state: UIApplicationStateBackground
 2012-12-21 08:16:08.229 Gamerton[34170:c07] [GTAppDelegate applicationDidEnterBackground:] state: UIApplicationStateBackground

 ... Reopen app

 2012-12-21 08:16:59.364 Gamerton[34170:c07] [GTAppDelegate applicationWillEnterForeground:] state: UIApplicationStateBackground
 2012-12-21 08:16:59.365 Gamerton[34170:c07] UIApplicationWillEnterForegroundNotification state: UIApplicationStateBackground
 2012-12-21 08:16:59.365 Gamerton[34170:c07] _UIApplicationDidRemoveDeactivationReasonNotification
 2012-12-21 08:16:59.366 Gamerton[34170:c07] [GTAppDelegate applicationDidBecomeActive:] state: UIApplicationStateActive
 2012-12-21 08:16:59.366 Gamerton[34170:c07] UIApplicationDidBecomeActiveNotification state: UIApplicationStateActive
 2012-12-21 08:16:59.366 Gamerton[34170:c07] UIApplicationResumedNotification state: UIApplicationStateActive
 2012-12-21 08:16:08.230 Gamerton[34170:c07] UIApplicationDidEnterBackgroundNotification state: UIApplicationStateActive
于 2012-12-21T16:19:01.467 に答える
0

UIApplication ドキュメントから:

UIApplicationStateInactive
The application is running in the foreground but is not receiving events. 
This might happen as a result of an interruption or because the application
is transitioning to or from the background.

そのため、アプリがバックグラウンドにあり、すぐにフォアグラウンドになる可能性がありますが、現在は移行中です。

于 2012-12-06T22:07:47.400 に答える