今回は画面遷移を実装していこうと思います。
画面遷移を実装するには、
StoryBoard
で実装する- コードで実行する
といった大きく分けて2つのやり方がありますが、今回はコードで実装していきます。
なぜこの2つの選択肢でコードを採用しているかというと、StoryBoard
で実装する場合にはSegue
を使用しますが、そうした場合に1つのStoryBoard
に全てのViewController
を集約する形になり、共同開発の場合にコンフリクトの嵐になってしまいます。なので僕はコードで実装する方を推奨しています。
Contents
画面遷移のやり方
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」
に変わったように自分の作成してるプロジェクト名に変わります。
遷移先の画面を作成したのでここからは実際に遷移する実装をしていきましょう。
今回は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]
で取り出すことができます。
ビルドしてみます。
画面遷移と実際に記事の中身が表示されるようになりました!
今回のコードはこちらでも確認できるのでよかったらご確認ください。