質問: self.storyboard?.instantiateViewController(withIdentifier: "second") present(secondVC!, animated:true, completion:nil) } ``` ボタンと接続させるコードを書いたんですが、`present(secondVC!~....`の、`secondVC`に`!`がつくのかよく理解できません。オプショナル型にすれば解決することはわかったのですが、これからも頻発しそうなエラーなので具体的な理由を教えていただけないでしょうか?よろしくお願いします。
回答: あなたのコードのこの行: ``` let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "second") ``` 使用している`instantiateViewController(withIdentifier:)`メソッドの戻り値型はオプショナルではない`UIViewController`と定義されていますが、そのメソッドはオプショナルチェイニング(`?.`)の中で呼び出されています。 オプショナルチェイニングでは、`?.`の左辺の`self.storyboard`が`nil`だった場合、式全体として`nil`を返さないといけないので、`self.storyboard?.instantiateViewController(withIdentifier: "second")`という式の戻り値型はオプショナルの`UIViewController?`になるのです。 従って、それを初期値として宣言された`secondVC`のデータ型も`UIViewController?`となり、オプショナルが許されていない場所で使うためには強制アンラップ(`!`)等の対処が必要になるわけです。(`secondVC`のデータ型がどのように型推論で決定されたかは、カーソルをそこにおいてXcodeの右サイドバーにあるQuick Helpを見れば表示されます。) ちなみに強制アンラップの`!`は、「100%絶対に`nil`にならないという自信があるとき以外は使わないこと」というのはご存知かと思いますが、最終的に強制アンラップを行う必要があるのでしたら、できるだけ早めに適用した方が、想定外の`nil`のせいでアプリがクラッシュした時に、そもそもの`nil`が発生した場所を突き止めやすくなります。 ``` @IBAction func goSecond(_ sender: Any) { let secondVC = self.storyboard!.instantiateViewController(withIdentifier: "second") present(secondVC, animated:true, completion:nil) } ``` こちらのコードでは、`secondVC`のデータ型は非オプショナルの`UIViewController`となるので、`present(_:animated:completion:)`メソッドを呼ぶ際には`!`が要らないということになります。 (蛇足ながらコメントの一部を本文に移動させました。) もしご自分で十分調べる前にご質問いただいたのであれば、今後は事前に十分お調べの上で解決できない場合にご質問いただくようにお願いします。 とは言え今回の内容はオプショナルが絡むということ以外にはうまくキーワードを選ぶのが難しいため、なかなか思うような記事にヒットしなかったかもしれません。 オンラインで情報を探す時のコツですが、 * 「オプショナル」などのキモになる用語はできるだけ正確に使用する (残念ながらSwift用語には定訳と言えるものがないので、英単語のOptionalの方が良いかもしれません。それでもちゃんとたくさん日本語の記事が出てきます。) * エラーになる場合は、エラーメッセージを拾って検索キーワードに含める。もちろんswiftやiosと言った2語は常に含めた方が良いでしょう。 (ただし、「検索エンジンの上位に来る」のと「それが正しいあるいはベスト」かどうかは無関係なのでご注意を。) * 折に触れて公式ドキュメントも参考にする。 (英語版しかありませんが、単語さえわかれば読み解ける平易な表現です。) 検索エンジン・QAサイト・そして教本と、利用できるものはなんでも利用して、素晴らしいアプリを作成されることを期待しております。