[iOS][Swift3.0] 階層が深くなっても大丈夫なナビゲーションを実現するNavigationStack

2017.02.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Pushで画面遷移をさせて階層が深くなって戻るのが大変になった時に活躍しそうなNavigationStackを今回は試してみました。 通常Pushで遷移した時に左から右へスワイプのジェスチャをすると直前の画面に戻りますが、NavigationStackでは下記画像のように今まで遷移した画面が表示され、該当する画面をタップすることで、そこに直接戻ることが出来ます。

sample

ナビゲーションバーの戻るボタン"<Back"は通常通り直前の画面に戻ります(スワイプの動きのみ変更になります)。昨日ブログに書いたFoldingCellと同じRamotion Inc.という企業が作成しており、ライセンスはMITです。

Ramotion/navigation-stack

検証環境

今回は下記環境で試しています。

Xcode 8.2.1
Swift 3.0.2
CocoaPods 1.0.0

準備

導入

CocoaPodsで追加します。

use_frameworks!
target "ターゲット名"
    pod 'Navigation-stack'
end

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |configuration|
            configuration.build_settings['SWIFT_VERSION'] = "3.0"
        end
    end
end

画面の用意

Storyboard上でNavigationControllerをEmbedして、ボタンを押したら次の画面にPushで遷移するようにしました。

Main_storyboard

これをシュミレーターで起動すると単純にPushで画面遷移をするだけの動きになります。まだ何も入れてないので、左から右へスワイプのジェスチャは直前の画面に戻る標準の挙動です。

befor

実装

NavigationControllerにカスタムクラスを設定

NavigationControllerのカスタムクラスにNavigationStackを設定します。

カスタムクラスを設定

ViewControllerのソースコード

NavigationStackをインポートし、interactivePopGestureRecognizer.delegateを実装します。

ViewController.swift

import UIKit
import Navigation_stack

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

extension ViewController: UIGestureRecognizerDelegate {

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {

        if navigationController?.viewControllers.count == 2 {
            return true
        }

        if let navigationController = self.navigationController as? NavigationStack {
            navigationController.showControllers()
        }
        
        return false
    }
}

実行結果

シュミレーターで実行した結果です。左から右へスワイプのジェスチャをした時に今まで遷移した画面が表示されるようになりました。

after

さいごに

アプリ利用者にスワイプの挙動を認知させる必要はありますが、階層が深くなった時にこういう機能があるとすごく便利だと思いました。導入が簡単なのもポイント高いです。

追記 (2017/2/3

コメントにて教えていただきました。(ありがとうございます✨)

2年ほど前にリリースされたものですが、UINavigationBarのBackボタンをロングタップすると近しい動きをするものがあります。現在は3D Touchにも対応しています。

こちらも簡単にではありますが試してみました。

marty-suzuki/SAHistoryNavigationViewController

スワイプではなく、Backボタンを3Dタッチ(非対応の端末は長押し)で履歴が表示されます。

実行イメージ

導入&実装

CocoaPodsで追加し、

pod 'SAHistoryNavigationViewController'

NavigationControllerのカスタムクラスにSAHistoryNavigationViewControllerを設定すればOKでした。

CustomClass