iOS8で、起動時にUILocalNotificationの通知を消さないようにする方法

iOS8で、UILocalNotificationで登録した通知からアプリを起動するたびに、毎回消えるようになりました。
以前まで大丈夫だった状況で、消えるようになっていました。
たぶんぼくの環境だけではないと思うのですが、毎回消えるので困っていました。

以前は、通知センターに通知を残していればアプリを起動するというようなプチハックにも使えて便利だったのですが、上記のように少し挙動が変わり同じように動作させるには少しコツがあります。

考え方としては、UILocalNotificationを再度登録するだけです。

でも、通知センターから起動した場合はアプリの起動している状態によって3パターンに動作が分かれますので、それぞれに対して対応する必要があります。

パターンですが、以下のようになります。

  • アプリが完全に落ちている場合。
  • アプリがバックグラウンドで動作している場合。
  • アプリが現在フォアグラウンドで使用中の場合。

このパターンそれぞれをアプリで取得するには、applicationDetegateでいくつかのコードを書く必要があります。

まず、アプリが完全に落ちている場合ですが、application:didFinishLaunchingWithOptions:が呼ばれるので、launchOptionsからUIApplicationLaunchOptionsLocalNotificationKeyキーで通知があるかどうかを調べて、存在していればnotificationを再登録します。

if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {

    // 通知センターから呼ばれた
}

アプリが現在フォアグラウンドで使用中の場合とアプリがバックグラウンドで動作している場合は、application:didReceiveLocalNotification:が呼ばれます。
このときに、UIApplicationのapplicationStateで起動中かバックグラウンドから起動したのかを判別しなければなりません。以下のコードで判定できます。

if (application.applicationState == UIApplicationStateActive) {

    // 起動中
}

if (application.applicationState == UIApplicationStateInactive) {

    // バックグラウンドから呼び出し
}

この、パターン内で再登録すれば通知が消えずに済むのですが、バックグラウンドから呼び出したときにすぐ再登録すると削除されず、そのままで2つ登録されることになってしまいます。

理由を色々と推測しているのですが、結局のところよくわかっていません。
ライフサイクルで、application:didReceiveLocalNotification:が終わったあとに通知が消えます。
しかし、このメソッドの中でUIApplicationのscheduleLocalNotification:メソッドを呼ぶと、そのアプリのapplicationStateUIApplicationStateInactiveの状態で再度application:didReceiveLocalNotification:呼び出されることになります。
そのあたりの動作で通知センターから消えなくなって、登録だけ実行されるのでしょうか。

とりあえず、これを解決する方法はありますので早速工夫してみます。

まず、呼び出された通知を保持しておく変数を準備しておきます。
@interface AppDelegate ()

@property (nonatomic) UILocalNotification *calledNotification;

@end

これに、application:didReceiveLocalNotification:で渡されるnotificationを入れておいて、ライフサイクルで以降に呼ばれるapplicationDidBecomeActive:あたりで、再登録を呼び出せば、問題なく通知が消えないような動作を実現できます。

- (void)applicationDidBecomeActive:(UIApplication *)application{

    if (_calledNotification) {

     [application scheduleLocalNotification:_calledNotification];
    }

    _calledNotification = nil;

}

アプリの内容によっては、applicationDidEnterBackground:でアプリを閉じるタイミングで再登録してもいいですし、一度全ての通知を解除して必要な分を再登録するというアプローチでも良いと思います。

冒頭で述べたとおり、以前は、通知センターからアプリを起動するというようなテクニックが流行っていましたがiOS 8ではTodayウィジェットがありアプリのショートカットとして通知センターを使うのはもう必要がないかも知れません。

これからも更新を続けていきますので、Feedlyへの登録をお願いします!

follow us in feedly

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です