
iPhoneはAndroidのようにバックボタンがない代わりにスワイプ操作で前の画面に戻れるようになっています。
Ionicにもこの機能が実装されていますが、前の画面に戻ると何も表示されなくなるといった問題があるためにconfig.jsに
$ionicConfigProvider.views.swipeBackEnabled(false);
と書いてOFFにしてしまっていることが多いと思います。
しかし、iPhoneを使っている人にとってスワイプで前に戻るという操作は当たり前になってしまっているため、できないと違和感を感じてしまいます。実際にこの操作に対応しているアプリも多く、対応していない=イマイチといった印象を与えることにもなりかねません。
スワイプバックがうまくいかない原因
Ionicのスワイプバックで何も表示されなくなってしまう原因を探っていくと、どうやらキャッシュが関係しているようです。
テンプレートに
<ion-view cache-view="false">
と書いてあったり、コントローラーやサービスなどのjs側で
$ionicHistory.clearCache();
または
$ionicHistory.clearCache().then(function() {
$ionicHistory.clearHistory();
});
などのキャッシュクリアをおこなっていると、スワイプバックした際に表示される前画面が生成されずに白い画面となって動作に問題が生じてしまうようです。
スワイプバックを効くようにする方法
試しに上記のようなキャッシュを削除している箇所を全てコメントアウトしてconfig.jsを
$ionicConfigProvider.views.swipeBackEnabled(true);
とすると、ちゃんとスワイプバックが動作すると思います。
しかし、このままでは画面のキャッシュが残ってしまうため、情報が更新されないページも出てきてしまいます。
ページ毎にスワイプバックを禁止する
テンプレート側でスワイプバックを禁止する方法
画面の再描画以外にもon-swipe-right
やon-swipe-left
を使ってスワイプでタブ切り替えをおこなっているページがあると、スワイプバックの動作が不安定になることがあります。
コンフィグでスワイプバックを全体に許可した場合は都合の悪いページだけ個別にスワイプバックを禁止することで問題を回避します。
テンプレートに
<ion-view can-swipe-back="false">
と書いておくことでそのページはスワイプバックを禁止することができます。
コントローラー側でスワイプバックを禁止する方法
コントローラー側で制御したい時は
$ionicHistory.currentView().canSwipeBack = false;
のようにします。
$ionicConfig.views.swipeBackEnabled(false);
と書いてもそのページだけスワイプバックを禁止することはできないのでご注意ください。
$ionicHistoryでスワイプバックを禁止にできる理由
$ionicHistory.currentView().canSwipeBack
は参照用という認識でしたが、ionic.bundle.js中に
var currentView = $ionicHistory.currentView();
if (!backView || backView.historyId !== currentView.historyId || currentView.canSwipeBack === false) return;
という記述があったので$ionicHistory.currentView().canSwipeBack
にfalseをセットすることでスワイプバックが禁止できることが判明しました。
スワイプバックさせたくないページをまとめて処理
前のページのstateNameを調べてスワイプバックさせたくない場合は共通処理に下記のように入れておきます。
キャッシュクリア後に遷移した先でスワイプバックを禁止する
$ionicHistory.clearCache()
をおこなっている部分を検索し、$state.goがある場合はその下でスワイプバックを禁止すると白い画面が出てしまうのを防ぐことができます。
Ionic v1系のスワイプバックが正しく動かない理由
ionic.bundle.jsを見ると、$ionicViewSwitcherというリファレンスにも載っていないIonicの機能を使って前画面を生成しているようです。
var switcher = $ionicViewSwitcher.create(self, registerData, backView, currentView, true, false);
のような記述が見られるのですが、この時にキャッシュクリアされているなどの要因があると、正しく前画面が作られずに白い画面が出来上がってしまうことが原因と考えられます。
前画面の生成に失敗した場合はスワイプバックを禁止するという処理を作ることができれば、他のページに手を入れなくてもスワイプバックを活かすことができるかもしれません。
まとめ
テンプレートの<ion-view cache-view="false">
は本当に必要なのかを確認してみましょう。ページをコピペで作る際に入ってしまったり、何となくおまじないのように入れていることも多かったりします。キャッシュを削除していなければスワイプバックが正常に動作する可能性は高まります。
逆に画面の更新のためにどうしても必要としている場合は簡単には削除できません。
Ionic v1系のキャッシュは結構協力で$scope.$apply();
や$state.go(state, {}, {reload: true});
をやっても更新されないことがあるのでテンプレート側でのキャッシュのクリアが外せないことが多いです。
その場合はスワイプバックを防止することで対応しましょう。
ただし、スワイプバックを防止したとしてもアプリ内にバックボタンがあると、普通にバックした直後にスワイプバックするという操作により、結局白い画面になってしまうという問題もあります。これを防止するためにバックボタンを非表示にしたり、$ionicHistoryで履歴を消すといった対応をすると、元のアプリの利便性まで落ちてしまい、本末転倒となってしまいます。
その他にもログイン処理後などの思わぬところでスワイプバックをすると白い画面になってしまうこともありました。複雑なアプリの場合、Ionicが用意しているスワイプバックを正常に動作させるのは難しいかもしれません。
その場合、途中までスワイプした時に前の画面を見せるというのを諦めれば、$ionicGestureを使って自力で実装するといった方法が考えられます。
本来ならキャッシュに関係なく、スワイプバックが正しく動作するようにしてほしいところです。