・画面遷移の処理を別のファイルで一元的に管理するとなにがいいのか?
・ViewControllerから画面遷移の処理を別のファイルに記述することで、ViewController内の記述量が減少し、可読性が上がる。
・実装
では、実際にどのように用いるかを見ていく。基本的には1画面1Storyboardで構成する。
今回のサンプルでは、FirstViewController(初期画面かつ遷移元画面)からSecondViewController(遷移先画面)への画面遷移を行う。また、SeceneDelegateを使わないので削除する。代わりに、AppDelegate.swiftに以下のような記述を行う。
・AppDelegate.swiftの設定
AppDelegate.swift
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
Router.showRoot(window: window)
return true
}
}
・UIStoryboardのExtensionファイルの作成
Storyboard+.swift
//Storyboard生成をUIStoryboardのExtensionファイルを作成することで一箇所にまとめる
import UIKit
extension UIStoryboard {
//isInitialViewControllerが設定されているStoryboardを読み込む
static var firstViewController: FirstViewController {
UIStoryboard.init(name: "First", bundle: nil).instantiateInitialViewController() as! FirstViewController
}
static var secondViewController: SecondViewController {
UIStoryboard.init(name: "Second", bundle: nil).instantiateInitialViewController() as! SecondViewController
}
}
・SecondViewController(遷移先画面)
SecondViewController.swift
import UIKit
final class SecondViewController: UIViewController {
//StoryboardからViewControllerをインスタンス化
static func makeFromStoryboard() -> SecondViewController {
let vc = UIStoryboard.secondViewController
return vc
}
}
・Router(画面遷移の処理をまとめたファイルを作成する)
Router.swift
import UIKit
final class Router {
//初期画面の表示をするスタティックメソッド
static func showRoot(window: UIWindow) {
window.rootViewController = UIStoryboard.firstViewController
window.makeKeyAndVisible()
}
//SecondViewControllerへ遷移するスタティックメソッド
static func showSecond(from: UIViewController) {
let vc = SecondViewController.makeFromStoryboard()
show(from: from, to: vc)
}
}
//前の画面がNavigationControllerを設置していたらpushで、そうでない場合はmodalで遷移
private extension Router {
static func show(from: UIViewController, to: UIViewController, animated: Bool = true) {
if let nav = from.navigationController {
nav.pushViewController(to, animated: true)
} else {
from.present(to, animated: true, completion: nil)
}
}
}
・FirstViewController(遷移元画面)
FirstViewController.swift
import UIKit
final class FirstViewController: UIViewController {
//StoryboardからViewControllerをインスタンス化
static func makeFromStoryboard() -> FirstViewController {
let vc = UIStoryboard.firstViewController
return vc
}
@IBOutlet private weak var nextButton: UIButton! {
didSet {
nextButton.addTarget(self, action: #selector(tapNextButton(_:)), for: .touchUpInside)
}
}
@objc func tapNextButton(_ sender: UIResponder) {
//次の画面へ遷移
Router.showSecond(from: self)
}
}