MILLEN BOX

音楽好きの組み込みソフトエンジニアによるプログラミング(主にiOSアプリ開発)の勉強の記録

アプリが非アクティブになったことをViewControllerで検知する方法 [UIApplicationDelegate]

アプリがアクティブでなくなったことをViewControllerにて検知する方法について調べてみました。

自分ポイント1 - 非アクティブ時に実行されるメソッドについて

アプリが非アクティブになった時、AppDelegateの applicationWillResignActive が実行されます。
アプリが非アクティブになった時にやりたい処理は、このメソッドの内部に記載すればOKです。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    ...

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.

        //ここに非アクティブ時にやりたい処理を書く

    }

    ...

}

上記方法で「非アクティブになった時」にさせたい処理を書くこと原理上できますが、例えばその際にViewController内で宣言されたプロパティの値を変更したい場合はどうでしょうか。
そのプロパティはViewController内でのみ変更可能なため、上記方法では不可能です。
じゃあ、どのようにすれば??

自分ポイント2 - 非アクティブのViewControllerでの検知の仕方について

実はAppDelegateの親クラスUIApplicationDelegateのメソッドが実行される際、通知信号が出力されます。
今回はapplicationWillResignActiveが実行された際に出力される通知信号をViewControllerで受け取ってあげるように準備してあげれば、ViewControllerにて非アクティブを検知できます。
通知信号の受信の準備ですが、以下の順番でViewControllerにコードを追記していくと分かりやすいです。

  1. 通知信号を受け取った時に行うメソッドを、(処理内容の記載は空っぽで良いので)まず書いておきます。(rcvSignalOfNonActiveとします)
  2. ViewDidLoad辺りに以下のコードを追記します。このコードが「通知信号を受けとる準備」になります。
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "rcvSignalOfNonActive", name:UIApplicationWillResignActiveNotification, object: nil) 引数selectorには手順1で追加した通知信号を受け取った時に行うメソッドを書きます。
    引数nameに指定されているUIApplicationWillResignActiveNotificationは、applicationWillResignActiveが実行された際に出力される通知信号の名前です。

  3. 通知信号を受け取った時に行うメソッドrcvSignalOfNonActiveの内部処理を書きます。
    今回は特に何がしたいということはありませんので、print("\(__FUNCTION__) is called!")を書いて呼び出されたことを分かるようにしておきます。

  4. おっと忘れていました。
    ViewControllerが継承するクラスとしてUIApplicationDelegateを追記しておいてあげて下さい。

以下にコードを書いておきます。

import UIKit

class ViewController: UIViewController, UIApplicationDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "rcvSignalOfNonActive", name: UIApplicationWillResignActiveNotification, object: nil)  //UIApplicationWillResignActiveNotificationを受信した時のコールバック関数を登録
                
    }

    /**
     applicationWillResignActiveが呼ばれることによって出される信号UIApplicationWillResignActiveNotificationを受信した時に実行する関数
     ロックボタンやタイマーなどでスクリーンが非アクティブになった時に行いたい動作を記述する
     */
    func rcvSignalOfNonActive() {
        print("\(__FUNCTION__) is called!")
    }


}

実行後、ロックボタンなどを押すアクションをするとrcvSignalOfNonActiveメソッドが呼び出されるのが分かります。

自分ポイント3 - その他の通知信号

先にも書いていますが、通知信号が呼ばれるのは今回の非アクティブになるケースだけでなく、UIApplicationDelegateのメッソッドが実行された時にそれぞれ発生します。
そしてそれぞれ出力される通知信号は異なります。
参考URL1 : UIApplicationBackgroundRefreshStatusDidChangeNotification
参考URL2 : UIApplicationのNotificationsの一覧 - 強火で進め

これらの情報を使ってユーザーアクションに対する実行メソッドと信号を実際動かして見てみるの、面白そうです。