Xamarin.Forms の App Lifecycle の呼び出され方を調べたい 【iOS編】
今回は Xamarin.iOS のアプリケーションライフサイクルの動作を確かめてみたいと思います
というわけで iOS のアプリケーション状態遷移のおさらい
Not Running、Inactive、Active、Background、Suspended の 4つの状態があり、Suspended に遷移してもメモリは解放されないので、再開時にデータを復帰させる対応はいらなそう
上記を踏まえて iOS の動作確認用のアプリを作ります
スポンサードリンク
とりあえずブラウザを開く機能を追加
/// <summary> /// Web ブラウザを開くサービス /// </summary> public class OpenBrowserService : IOpenBrowserService { /// <summary> /// Web ブラウザを開く /// </summary> /// <param name="uri">Uri</param> public void OpenUri(string uri) { SimpleLogger.WriteLine(string.Format("open to {0}", uri)); UIApplication.SharedApplication.OpenUrl(new NSUrl(uri)); } }
さくっとブラウザ呼び出しを追加するのみ!
次に AppDelegate.cs を変更
// The UIApplicationDelegate for the application. This class is responsible for launching the // User Interface of the application, as well as listening (and optionally responding) to // application events from iOS. [Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { /// <summary> /// WillFinishLanching イベントハンドラ /// 起動プロセスは実行されたが、その状態の復元がまだ発生していない状態 /// </summary> /// <param name="uiApplication">アプリケーション</param> /// <param name="launchOptions">起動オプション</param> /// <returns>正常終了フラグ</returns> public override bool WillFinishLaunching(UIApplication uiApplication, NSDictionary launchOptions) { SimpleLogger.WriteLine(string.Format("WillFinishLaunching. AppState={0}", uiApplication.ApplicationState.ToString())); // ブラウザで開く機能を登録 App.Container.RegisterType<IOpenBrowserService, OpenBrowserService>(new ContainerControlledLifetimeManager()); return base.WillFinishLaunching(uiApplication, launchOptions); } /// <summary> /// FinishedLaunching イベントハンドラ /// 起動プロセスがほぼ終了した後、アプリの起動準備ができた状態 /// </summary> /// <param name="uiApplication">アプリケーション</param> /// <param name="launchOptions">起動オプション</param> /// <returns>正常終了フラグ</returns> public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions) { SimpleLogger.WriteLine(string.Format("FinishedLaunching. AppState={0}", uiApplication.ApplicationState.ToString())); global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); return base.FinishedLaunching(uiApplication, launchOptions); } /// <summary> /// OnActivated イベントハンドラ /// アプリケーションがアクティブになった直後に呼び出されます /// </summary> /// <param name="uiApplication">アプリケーション</param> public override void OnActivated(UIApplication uiApplication) { SimpleLogger.WriteLine(string.Format("OnActivated. AppState={0}", uiApplication.ApplicationState.ToString())); base.OnActivated(uiApplication); } /// <summary> /// OnResignActivation イベントハンドラ /// アプリケーションが Inactive になる直前に呼び出されます /// </summary> /// <param name="uiApplication">アプリケーション</param> public override void OnResignActivation(UIApplication uiApplication) { SimpleLogger.WriteLine(string.Format("OnResignActivation. AppState={0}", uiApplication.ApplicationState.ToString())); base.OnResignActivation(uiApplication); } /// <summary> /// DidEnterBackground イベントハンドラ /// Backgrond 状態に遷移した状態 /// </summary> /// <param name="uiApplication">アプリケーション</param> public override void DidEnterBackground(UIApplication uiApplication) { SimpleLogger.WriteLine(string.Format("DidEnterBackground. AppState={0}", uiApplication.ApplicationState.ToString())); base.DidEnterBackground(uiApplication); } /// <summary> /// WillEncodeRestorableState イベントハンドラ /// 任意のアプリデータ復帰が必要になった場合に呼び出されます /// </summary> /// <param name="uiApplication">アプリケーション</param> /// <param name="coder">シリアライズオブジェクト</param> public override void WillEncodeRestorableState(UIApplication uiApplication, NSCoder coder) { SimpleLogger.WriteLine(string.Format("WillEncodeRestorableState. AppState={0}", uiApplication.ApplicationState.ToString())); base.WillEncodeRestorableState(uiApplication, coder); } /// <summary> /// WillEnterForeground イベントハンドラ /// Foreground 状態に遷移した状態 /// </summary> /// <param name="uiApplication">アプリケーション</param> public override void WillEnterForeground(UIApplication uiApplication) { SimpleLogger.WriteLine(string.Format("WillEnterForeground. AppState={0}", uiApplication.ApplicationState.ToString())); base.WillEnterForeground(uiApplication); } /// <summary> /// WillTerminate イベントハンドラ /// アプリが終了する直前に呼び出されます /// </summary> /// <param name="uiApplication">アプリケーション</param> public override void WillTerminate(UIApplication uiApplication) { SimpleLogger.WriteLine(string.Format("WillTerminate. AppState={0}", uiApplication.ApplicationState.ToString())); base.WillTerminate(uiApplication); } }
DI コンテナに先ほどのサービスクラス実体を登録するのと、各種状態遷移のイベントハンドラをログ出力つきで追加しました・・・Windows Phone に比べると多い;
あとは実行、Windows Phone の時と同様に下記のような操作を順にやってみます
- アプリ起動
- 次画面に遷移
- ブラウザで Xamarin ホームを開く
- アプリに戻る
- トップ画面に戻る
- OS ホームに戻る
- 再度アプリに戻る
- アプリを終了
- 再度起動
操作の様子はこんな感じ
出力されたログは・・・
AppDelegate.WillFinishLaunching WillFinishLaunching. AppState=Inactive AppDelegate.FinishedLaunching FinishedLaunching. AppState=Inactive App.OnStart started. AppDelegate.OnActivated OnActivated. AppState=Active TopPage.xaml.OnAppearingTopPage Appearing. SecondPage.xaml.OnAppearingSecondPage Appearing. AppDelegate.OnResignActivation OnResignActivation. AppState=Active App.OnSleep sleeped. AppDelegate.DidEnterBackground DidEnterBackground. AppState=Background AppDelegate.WillEnterForeground WillEnterForeground. AppState=Background AppDelegate.OnActivated OnActivated. AppState=Active App.OnResume resumed. TopPage.xaml.OnAppearingTopPage Appearing. AppDelegate.OnResignActivation OnResignActivation. AppState=Active App.OnSleep sleeped. AppDelegate.DidEnterBackground DidEnterBackground. AppState=Background AppDelegate.WillEnterForeground WillEnterForeground. AppState=Background AppDelegate.OnActivated OnActivated. AppState=Active App.OnResume resumed. AppDelegate.OnResignActivation OnResignActivation. AppState=Active App.OnSleep sleeped. AppDelegate.DidEnterBackground DidEnterBackground. AppState=Background AppDelegate.WillTerminate (アプリ終了後、デバッカーも停止した)
やはり Windows Phone と同様にアプリ終了するまではアプリに戻ると OnResume が呼ばれるようです
操作が速すぎて Background から Suspended まで行くことがなかったのかとブラウザを開いたあとに 10 分待ってみましたが結果は変わらず
おそらくデバッグ起動だと Suspended にならないのかと思います
いずれにせよ iOS も OnResume を通ったときだけセッションデータを復帰させればよさそうです、ただアプリデータはメモリに残っているので何もしなくてよさそうですが