子ザルでもわかるswift画面遷移超入門（Present Modally基礎）

こんにちは。XcodeでiPhoneアプリ開発の練習をしていますが、なかなか体型的に使い方を学べるマテリアルが少ないなあと感じています。

初心者が戸惑う項目の一つが画面遷移。他の記事でも画面遷移については、たくさんまとめられていましたが、それでも真の初心者だった頃に読んでも初歩の部分がなかなか理解できませんでした。今回は、そんな「サルでもわかる」系記事を読んでもわからない真の初心者向けに、さらに噛み砕いた「子ザルでもわかる」画面遷移の解説記事を書いていきます。

Swift以外の言語に触れたことがあるエンジニアさんよりも、そもそもプログラミング経験のない真の初心者向けの記事となっております。

今回主に扱うのは以下の3項目です。

- 新規プロジェクト作成から、Present Modallyという方式でシンプルな画面遷移をする。
- 画面遷移後、元の画面へ戻る。
- ここまでの作業でよく出るエラー、躓きポイントへの対処法がわかる。

## １.新規プロジェクトファイルを作ろう
「真の初心者」のための記事ですし、まずはプロジェクトファイルの新規作成から始めましょう。

画像の通り、まずは「App」を選択してNextを押します。プロジェクト名をつけて、各項目が画像の通りになっているか確認します。今回はscreenTransitionというプロジェクト名にしました。そして任意の場所に保存します。「create Git repository on my Mac」のところは、Gitで変更履歴管理をしたいときに選択するところです。現時点ではチェックしていなくても大きな問題にはならないはずです。

![スクリーンショット 2021-06-24 8.02.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/8ac5034c-95f8-f606-b09d-4adb1b1ed8be.png)

![スクリーンショット 2021-06-24 8.02.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/b29ad7cf-a501-bd99-1e5c-2478c15710e4.png)

![スクリーンショット 2021-06-24 8.02.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/e00a1337-2037-23cd-941f-b3537f731fd8.png)

さて、プロジェクトファイルができました。たまに以下のアテンションが出ますが、アプリの製作者情報がきちんと設定されていないという警告です。おそらく前段でcreate Git repository on my Macにチェックを入れると最初これが出ると思います。とりあえずは「cancel」で問題ありません。

![スクリーンショット 2021-06-24 8.02.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/97d1e193-233b-1db4-82d7-fa7fd3a625bc.png)

プロジェクトが立ち上がると、最初に以下のような設定画面が出てくると思います。細かく知っておく必要はありませんが、現時点では青いチェックは画像のように「iPhone」と「Portrait」だけにしておくと良いと思います。この設定は、アプリをiPadにも対応させるか、デバイスを横向き・逆さにした時の動きにも対応させるかどうかの設定です。今回はiPhoneのみ・縦向きのみの動作対応とします。

ちなみに一番上のDisplay Nameのところで、入力した名前がアプリの名前になります。アプリの名前とは、実際にデバイスでダウンロードした時に、アイコンの下に表示される名前のことです。

![スクリーンショット 2021-06-24 8.02.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/d43db230-dd5a-9dac-448a-bdcec38cb872.png)

画面の左の方を見ると、以下のようなファイルのセットが生成されます。画像のように、上部のファイルアイコンをクリックしてください。初心者の段階で扱うのは主に以下の３つです。

①ViewController.swift
画面に紐づくプログラムを書いていくファイルです。この次に説明するMain.storyboardファイルで置いたボタンを押した時に、どのような挙動をするかなどをコードで記述していきます。今後は画面を一つ増やすたびに、新しい.swiftファイルが必要になってきます。

②Main.storyboard
画面の見た目を作っていくファイルです。開くと白い画面が一つデフォルトで入っています。ここにボタンなどのパーツを置いていきます。

③Assets.xcassets
今回は使いませんが、画面に表示させたい画像などを置いておくフォルダです。

![スクリーンショット 2021-06-24 8.02.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/f3b92caa-a103-b9ed-fab1-8dfad9dfa51f.png)

## ２.ボタンによるPresent Modallyの画面遷移（スワイプで戻れるパターン）
最初に紹介するのは、コードを書かない一番単純な画面遷移の方法です。手順は以下の４つです。

①新しい画面を追加する
②新しい画面用の.swiftファイルを作る
③ボタンを置く
④ボタンから遷移先の画面に引っ張る

### ①新しい画面を追加する
Main.storyboard右上の＋ボタンを押して、「viewController」で検索し、ドラッグしてきます。途中まで入力すると、予測変換で出てくるはずです。

![スクリーンショット 2021-06-24 8.03.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/3b29a421-4a73-ad76-f5c3-9d6ea5f8d6b0.png)

以下のように新しい画面が追加されました。

![スクリーンショット 2021-06-24 8.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/46469370-161f-50cc-dab5-01061300d9df.png)

わかりやすいように新しい画面に背景色を追加しましょう。画像の通り右側「View」というメニューの「Background」で色を選択します。

![スクリーンショット 2021-06-24 8.03.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/beb25261-bc61-a0f8-b2bf-c666a9aa4c7b.png)

### ②新しい画面用の.swiftファイルを作る

黄色のフォルダのところで右クリックメニューを開き「New File」を選択し、「Cocoa Touch Class」を選択します。今回は「NextViewController」という名前にします。

![スクリーンショット 2021-06-24 8.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/5e948924-d62d-d1f8-618c-c545339e0c0e.png)

![スクリーンショット 2021-06-24 8.03.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/69550691-b4de-8575-dd70-fad41ee1fb77.png)

![スクリーンショット 2021-06-28 5.48.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/9c590a3c-8a3b-3d63-7908-f6141fadaa56.png)

さて、このままではただ新規ファイルを作っただけで、画面と紐付いていません。紐付けましょう。Main.storyboardで新しい画面の上の長方形のエリアをクリックした状態にします。そして右側の「Custom Class」メニューの一番上に「NextViewController」と入力すると、先ほど新規作成した.swiftファイルが画面と紐づきます。長方形エリアをクリックしておかないと予測変換が出てきませんので注意。

![スクリーンショット 2021-06-24 8.03.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/c318016b-1fcf-2fc3-3ddf-6e56e3d5ae5f.png)

### ③ボタンを置く

新しい画面を追加した時と同じように、右上の＋ボタンを押し「Button」で検索します。見つかったら遷移前の画面にドラッグ&ドロップします。
Buttonの文字や大きさを変える方法は今回割愛しますが、右側のメニューを探すとcolor、sizeなど大体わかると思います。

![スクリーンショット 2021-06-24 8.03.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/e5d3a946-3354-ae3a-4e59-e61803638915.png)

### ④ボタンから遷移先の画面に引っ張る

Controlキーを押しながら、配置したボタンを遷移先画面までドラッグします。遷移先画面で離すと以下のようなメニューが出てくるので、今回は「Present Modally」を選択してください。

すると画面間に矢印が出てきます。この矢印をセグエと言い、画面遷移の流れを示します。

![スクリーンショット 2021-06-24 8.03.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/ff8bfb44-a448-89da-5cdd-2cef13b38a6f.png)

![スクリーンショット 2021-06-24 8.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/84e56d2b-4386-7629-740e-c4e14a20c28f.png)

これで完了です！

シュミレータを立ち上げて動きを見てみましょう。Xcode画面上下のiPhoneの型名が揃っていることを確認してから左上の三角ボタンを押します。私はいつもiPhone11に揃えています。

ちなみにシミュレータでは、パソコンのクリックがiPhoneのタップになります。スワイプするときは、クリックしながらドラッグです。タッチパッドを優しくタップしたりスワイプしても何も反応しないのでご注意ください。（案外やってしまう）

ボタンを押すと下から画面がにょきっと出てきます。これがPresent Modallyという画面遷移になります。現れた画面を下にドラッグすると元の画面に戻ります。

![スクリーンショット 2021-06-24 8.03.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/ce789851-11f7-d166-476a-5d4038dee11f.png)

<img width="700px" alt="1.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/ed1e67ce-1aef-6fa3-1de9-b915b103eef5.gif">

## ３.ボタンによるPresent Modallyの画面遷移（スワイプで戻れないパターン）
２.ではPresent Modallyで画面遷移をして、出てきた画面をスワイプすることで閉じることができました。ここではPresent Modallyで、スワイプで閉じることができない設定にした場合にボタンとコードで画面を閉じる方法を見ていきます。

手順は以下の①〜③です。（前提条件として２.の①〜④までは完了していること）
※２.と逆方向に、ボタンから元の画面にドラッグするというような単純な作業ではないので注意！

①SegueのPresentationをFull Screenにする
②ボタンを置き、ソースコードにボタンを引っ張ってきて紐付ける
③現れたActionの領域にdismissを記述する

### ①SegueのPresentationをFull Screenにする
以下の画像のようにセグエを選択した状態で、右側の「Storyboard Segue」メニューの「Presentation」を「Full Screen」にします。

![スクリーンショット 2021-06-24 8.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/a5dbf403-0fcc-5156-b27a-f79bd069c1e3.png)

### ②ボタンを置き、ソースコードにボタンを紐付ける
前と同じ手順で青い方の画面に戻るボタンをおきます。わかりやすいようにボタンの文字と文字色など変えてあります。そして下の画像の通り五本線のボタンをクリックし、「Assistant」をクリックします。すると新しい画面追加時に作成したNextViewController.Swiftファイルが右側に表示されるのを確認してください。

うまくいかない場合は出てきた画面を×ボタンで閉じ、左のメニューでOptionキーを押しながらNextViewController.Swiftをクリックするとうまくいくはずです。

![スクリーンショット 2021-06-24 8.04.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/81cdd73c-f0d5-5f48-4467-2da96b66f2f0.png)

![スクリーンショット 2021-06-24 8.04.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/d57f7b73-904c-10c6-02af-7f0853e2148f.png)

それでは、Controlキーを押しながら、配置したボタンをソースコードファイルにドラッグしましょう。viewDidLoad関数の下に引っ張ってきましょうか。viewDidLoad関数の上の方や中に引っ張ってしまうと、想定とは違った動きをしてしまうので注意してください。

すると以下画像のようなメニューが出てくるので、一番上が「Action」になっていることを確認し「backButton」と名前をつけてConnectを押しましょう。ソースコードに、ボタンを押した時の処理を記述する部分が追加されます。
※行番号のところに◉が表示されていることが大切です。現れた記述やボタンを闇雲に削除してしまうとエラーの元になります。紐付けをやり直したい時は適切な手順で削除する必要があるのです（４.のコラム参照）。

![スクリーンショット 2021-06-24 8.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/0370d564-ac73-c442-9359-ebf1c45aab3f.png)
![スクリーンショット 2021-06-24 8.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/decfae79-729c-e939-a1ab-ff0fb3e2175c.png)

### ③現れたActionの領域にdismissを記述する

それでは初めてのswiftコードを書いてみましょう。追加されたbackButtonアクションの中に、以下のようにdismissを記述します。dism...と入力すると予測変換で出てきます。予測変換で出てこない場合は記述場所がおかしいので注意してください。最初に出てくるのはテンプレートなので、灰色の部分をtrueとnilに書き換えてください。

![スクリーンショット 2021-06-24 8.04.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/0820fe68-939a-d3c8-e98d-7e90cfe2dffb.png)
```dismiss(animated: true, completion: nil)
```
さあ、これだけで完成です！シミュレータで動きを確認しましょう。

<img width="700" alt="2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/ecc0bb3c-9015-a56d-73b1-661df72c4de5.gif">

ちなみに私は、シミュレータ自体は正しく動作しましたが、シミュレータを閉じると「Thread 1: signal SIGTERM」というエラーが出てしまいました。これについても４.のコラムで解説します。

![スクリーンショット 2021-06-24 8.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/752f7a3d-6054-d673-ce07-d34316c8e3df.png)

## ４.【コラム】ボタンの紐付けに失敗した時の適切なやり直し方法

ここまでで、ボタンをソースコードにドラッグしてくるという動きがありました。しかし間違えてドラッグしてしまい、現れたActionの記述を削除してやり直したいこともありますよね？出てきたActionの記述を消すだけでは不十分なので、一回エラーを出してから適切なやり直し方をみていきましょう。手順は以下の①と②です。

①現れたActionの記述を削除する
②紐付け履歴を削除する

### ①現れたアクションの記述を削除する

それではまず、現れた「backButton」アクションをそっくり丸ごと削除します。左の◉が残ってしまうことがあるので、ちゃんと消えるように空行も数回削除してみてください。
その後、改めてボタンからソースコードにドラッグして「backButton2」という名前をつけてみましょう。前の画面に戻るためのdismissの記述も追加しておきます。

![スクリーンショット 2021-06-24 8.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/65ab06f6-11fb-c988-138d-5bb0de442779.png)
![スクリーンショット 2021-06-24 8.05.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/c31c2e4f-8ed6-da5f-2d1c-c1d2e3a6f531.png)

それではこの状態でシミュレータを立ち上げ、戻るボタンを押してみましょう。すると以下のようなエラーが出るはずです。

![3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/955c22ca-1897-09c9-1ded-eacbce0f5aaa.gif)

```Thread 1: "-[screenTransition.NextViewController backButton:]: unrecognized selector sent to instance 0x133705db0"```

これは、最初に削除した「backButton」の紐付け履歴が残っているのに、コードに「backButton」アクションがないので、Xcodeさんがめちゃくちゃ困っている状態です。

### ②紐付け履歴を削除する

ここからが大切です。見た目上はコードが書き換えられてうまくいったように見えますが、アプリの裏側ではまだ紐付けされた情報が残っているため、それを削除する必要があります。
青い画面の上の長方形のエリアにある、一番左のボタンをクリックします。

![スクリーンショット 2021-06-24 8.05.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/9d8a0f1a-7e70-cc1e-0c17-95c775948c45.png)

すると以下のメニューが出てきます。下の方に、明らかにエラーっぽい「！」がありますね。これが削除したはずの「backButton」の紐付け履歴です。ここの×ボタンをクリックして消し去りましょう。言わずもがなですが、その上の「backButton2」は新しく紐付けた情報で正しいものなのでそのまま残します。

![スクリーンショット 2021-06-24 8.05.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/f873f6e0-455e-d238-92c8-74a06d54b11e.png)

シミュレータで再度確認してみてください。いかがでしょうか？問題なく戻るボタンが押せたはずです。

３.で前述しましたが、ボタンを押したときや、シミュレータを閉じた時に以下の画像のアテンションが出ることがあります。このエラーを検索してみると以下のような記事が出てきます。
[・【Swift】「Thread 1: signal SIGABRT」エラーが出るときの原因](https://rightcode.co.jp/blog/information-technology/swift-thread-1-signal-sigabrt-error-cause)
[・Thread 1: signal SIGABRTの解決法](https://teratail.com/questions/230962)
記事をみるとわかるように、やはりボタンとソースコードの紐付けがうまくいっていない時に出るエラーであるようです。

[・Thread 1: signal SIGABRT](https://teratail.com/questions/230962)の解決法によるとこの「Thread 1:signal SIGTERM」の部分は厳密にはエラーの説明をしているわけではないようです。下のコンソールの「Reason」以下に詳細が現れるので、その部分をコピペして検索してみましょう。

ちなみに私は「Reason」が出てこなかったので結局原因不明ですが、まあアプリクラッシュしなかったので今回はよしとします。一度誤った紐付けをして何度かやり直しをしたため、それが原因になっていると考えています。

![スクリーンショット 2021-06-24 8.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1676583/d40e73dd-9744-e298-2cfe-11831f79bf9f.png)

## ５、最後に

以上、iPhoneアプリ制作にて最も基本的な画面遷移方法かと思われるPresent Modallyの２通りの遷移方法と、気をつけるべき点について解説してきました。今回は細々した項目の説明が多く画面遷移のバリエーション自体をあまり紹介できませんでした。今後はその他の画面遷移方法や、画面遷移アニメーションをカスタマイズする方法について理解を深めていければなと思っています。

###以下参考にした記事

- [Segueの選択肢の意味合い](https://qiita.com/motamura/items/7e061a52be33a39267b7)
- [モーダルとは？](https://wepress.web-magazine.jp/2018/08/30/modal/)
- [【Swift】「Thread 1: signal SIGABRT」エラーが出るときの原因](https://rightcode.co.jp/blog/information-technology/swift-thread-1-signal-sigabrt-error-cause)
- [Thread 1: signal SIGABRTの解決法](https://rightcode.co.jp/blog/information-technology/swift-thread-1-signal-sigabrt-error-cause)
- [Views without any layout constraints may clip their content or overlap other views.](https://teratail.com/questions/230962)
- [【Swift】画面遷移について](https://qiita.com/10Ne2Cx1To426/items/a1df8e87ea1129920183)
- [[Swift]segueを使った画面遷移、segueを使わない画面遷移](https://qiita.com/marcy731/items/942bd40a8339daeeff97)
- [画面遷移　まとめ swift](https://qiita.com/pitto/items/e8695834dace6d3dd2e7)
- [コードで画面遷移 swift](https://qiita.com/pitto/items/b1fe7e9178c9e99d7c34)
- [【Swift】 画面遷移を行う](https://qiita.com/kanae_/items/a0637df2932ce63a1e67)
- [画面遷移の方法](https://qiita.com/0xTJtrFMRTbrbho/items/2bb001b047f9b97a0b71)
- [Swiftコードで画面遷移](https://qiita.com/hirayama-tk/items/081f4f8f9e063f7fef8b)
- [Swift（UIKit）の画面遷移](https://qiita.com/omatty198/items/cb037b8aa8b9b410be03)
- [Storyboardで画面遷移を学ぶ](https://qiita.com/n0bisuke/items/ba9e76254c4e577cae2e)
- [【Swift】簡単な画面遷移まとめ](https://qiita.com/antk/items/213fdd144a5391e10c70)