今回は画面遷移を実装していこうと思います。
画面遷移を実装するには、
StoryBoardで実装する- コードで実行する
といった大きく分けて2つのやり方がありますが、今回はコードで実装していきます。
なぜこの2つの選択肢でコードを採用しているかというと、StoryBoardで実装する場合にはSegueを使用しますが、そうした場合に1つのStoryBoardに全てのViewControllerを集約する形になり、共同開発の場合にコンフリクトの嵐になってしまいます。なので僕はコードで実装する方を推奨しています。
画面遷移のやり方
iOSアプリでは画面遷移の仕方が2通りあります。
- Modal遷移
- Push遷移
この2つがあります。
それぞれについて説明していきます。
その前に下準備として、前回までにapiから記事を取得してTableViewに表示させたので記事セルをタップしたら記事詳細ページに遷移するというようにしていこうと思います。
apiからTableViewに表示する流れはこちらの記事で解説しています。
なので以下の2つを作成しました
- ArticleDetail.storyboard
- ArticleDetailViewController.swift
作成の手順を説明していきます。
ArticleDetailViewController.swiftの作成
まずArticleDetailViewController.swiftを作成していきます。新しいファイルを作成する場合はそのファイルを置きたい階層のフォルダを右クリックして「New File」を選択すると作成できて、その場所に置かれます。今回はSampleAppの下に置くことにしたのでSampleAppを右クリックしました。
そうするとこのような画面がでてくるので今回はCocoa Touch Classを選択します。
ファイル名を指定します。今回はArticleDetailViewControllerとしました。Xibファイルは作成しないのでチェックは入れないようにしましょう。
そのまま進むとこのようになって作成完了です。
ArticleDetail.storyboardの作成
次にArticleDetail.storyboardの作成をします。
先程と同様に「New File」を選択します。
今回は「Storyboard」を選択します。
同様に作成することができますが、storyboardの場合作成されたものは中身がからっぽになります。
ここからViewControllerを追加していかないといけません。
手順は、このように右下のリストから「ViewController」をドラッグ&ドロップしてきます。
「Is Initial View Controller」にもチェックを入れるようにしましょう。これは最初のViewControllerであるということを表します。
次にこのStoryboard上のViewControllerと実際にこのViewControllerの挙動が書かれているClassを紐づける必要があります。
その手順は下のように、Classの部分に「ArticleDetailViewController」と設定します。
ある程度補完が効くようになってるので最初の数文字打って、エンターを押せば大丈夫です。
ちゃんと紐付けができている場合はClassの下のModuleの部分が薄い文字で「none」から「SampleApp」に変わったように自分の作成してるプロジェクト名に変わります。
NavigationControllerの設定
遷移先の画面を作成したのでここからは実際に遷移する実装をしていきましょう。
今回はPush遷移で実装していきます。
まずはNavigationControllerを設置していきます。
記事一覧画面のStoryboardはMain.storyboardなのでここに設置していきます。
このようにViewControllerを選択した状態で「Editor」→「Embed In」→「Navigation Controller」を選択すると作成することができます。
これでNavigationControllerが設置されました。
画面遷移のコードを実装
実際に画面遷移の実装をしていきます。
今回は記事セルをタップしたときにその記事の詳細ページに飛ぶようにしたいのでセルをタップしたときに遷移するようにコードを書いていきます。
セルをタップしたとき実行されるようにするにはdidSelectRowAtのメソッドに書けばよかったですね。これに関しては、こちらの記事で解説しています。
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = UIStoryboard(name: "ArticleDetail", bundle: nil).instantiateInitialViewController()!
navigationController?.pushViewController(vc, animated: true)
}
}
このように実装しました。
UIStoryboard(name: "ArticleDetail", bundle: nil)
のnameの部分を1文字でも間違えるとクラッシュしてしまうので注意です。
instantiateInitialViewControllerというのは先程Storyboardを作成したときに「Is Initial View Controller」のチェックをいれたViewControllerがインスタンス化されます。
navigationControllerに対してインスタンス化したviewcontrollerを引数として渡してpushViewControllerを呼ぶと遷移することができます。
実際にビルドします。
このように画面遷移できるようになりました。
NavigationControllerを設置したのでデフォルトでナビゲーションバーが出現するようになり戻る機能も備わっています。
記事内容が出てくるようにする
無事画面遷移することが出来るようになりましたが、遷移した画面は何もでてこないので記事の詳細が出てくるようにします。
Articleのbodyが出てくるようにします。
とりあえずこのようにStoryboardにlabelを設置しました。レイアウトはテキトーに上下左右マージンを20pxにしました。行数は0に設定指定しています。
次にArticleDetailViewController.swiftでこのように変更しました。
import UIKit
class ArticleDetailViewController: UIViewController {
@IBOutlet weak var bodyLabel: UILabel!
var article: Article?
override func viewDidLoad() {
super.viewDidLoad()
bodyLabel.text = article?.body
}
}
bodyLabelをIBOutletで設定して、articleのbodyが入るようにしています。
記事ごとにarticleが異なるので実際にどのarticleが入るかは記事一覧で選択されたarticleをここに渡すようにしないといけません。
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = UIStoryboard(name: "ArticleDetail", bundle: nil).instantiateInitialViewController()! as! ArticleDetailViewController
vc.article = articles[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
}
}
このように書き換えました。
まずlet vcの部分ですがArticleDetailViewControllerにキャストするように書き換えました。
そうすることでarticleプロパティに値をセットできるようになります。
セットするarticleはタップされた記事なのでarticles[indexPath.row]で取り出すことができます。
ビルドしてみます。
画面遷移と実際に記事の中身が表示されるようになりました!
今回のコードはこちらでも確認できるのでよかったらご確認ください。
