*

Swiftの画面遷移とエラー – コタツと台所にて作るアプリ 7

   

PAK86_seisakudb20140517500

出だしでいきなりつまずいたが、なんとかStoryBoardの使い方もわかった。

後はちまちまとImageViewやらUIButtonやらをViewに配置していく。

UIパーツの配置が完了したら、今度は各Viewに対応するViewControllerを作成し、UIパーツをViewControllerにドラッグして、IBOutletでつなげていく。

ここまではObjective-Cの時と変わらず、スムーズに進んだ。

「よし。順調、順調。」

続いて、ボタンを押したら次画面に遷移するように処理を作っていく。

いよいよ本格的にSwiftでのコーディングである。

「・・・えっと。Objectvie-Cの時と同じなんだっけ?」

コード補完で、それなりのメソッドは出てくるが、果たしてこれでいいのだろうか。。。

そして、またいそいそとGoogle先生に聞くのだった。

Swiftでのボタンによる画面遷移

今回のボタンの画面遷移としては、次のことを考えました。

①UIButtonのaddTargetメソッドで、ボタン押下時のメソッドを指定
②①で指定したメソッドを作成し、その中で画面遷移を記述する。

基本的な画面遷移の動作であれば、StoryBoard上でUIButtonを次の画面にドラッグして画面遷移を定義すれば、上の②の処理は書く必要はないと思います。

ただ、ボタン押下時にいろいろ処理はしたいですし、ソースを見ればどこに画面遷移するか把握できるようにしておきたいといこともあり、私は②もソースで記述するようにしています。

Objective-CからSwiftへの変換

Objective-CとSwiftは言語は異なりますが、UIKitに関していえば、従来とあまり変わりはありません。

その為、Objective-Cで使っていたメソッドと同じものを使いたいと思った時は、似た様なメソッド名や引数のものを選択すれば、大体は同じだったりします。(かなり乱暴なこと言ってますが。)

Objective-CからSwiftへの変換は以下の記事を参考にさせていただきました。

【Objective-CとSwift比較】※今後追加予定

UIButtonのaddTargetは以下の通り、あまり変わりありません。

//Objective-C
[btn addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
//Swift
btn.addTarget(self, action: "onClick:", forControlEvents: UIControlEvents.TouchUpInside);

Swiftでの画面遷移

Swiftでの画面遷移はどうするんだっけ?と思って最初に参考にしたのが、以下のサイトでした。

015 UIViewControllerで画面遷移する

ここのサイト様はSwiftが出始めから、すでにSwiftのコードが載っていてかなり参考にさせてもらいました。

Swiftでの画面遷移についても書かれているので、とりあえずはこれに沿って処理を作ればいいかなと気軽に考えて処理を書いて、実行してみました。

すると、次のエラーが。

fatal error: unexpectedly found nil while unwrapping an Optional value

Google翻訳
致命的なエラー:オプションの値を開梱しながら、予想外にnilを発見

(私的脳内変換:)
Optional指定で!マーク(エクスクラメーションマーク)を設定している変数にnilが入ってきたんですが、これは一体どいうことでしょうか?
!マークが指定されている変数へのnilはご法度中のご法度。
いわば、男子禁制の神聖なる女子校に不埒な男が侵入してきたのと同義です。そこのところお分かりでしょうか?(深いため息)
よって、即刻アプリケーションを止めましたので、nilの抹殺・・・もとい排除、またはその変数を?マークにして、nilを許容、つまりは男女共学に変更するなりしてくださいね。よろしく。

朝早いから頭がおかしくなってるな。

だけど、なんら難しいことしてないのにエラーとはどういうことだろうか。

と、思いながらOptionalの!指定ってどこで使ってたっけと思ったら、IBOutleの宣言で使われていました。

@IBOutlet weak var titleImageView: UIImageView!

この宣言されている部分でnilが入ってきているということらしいのです。

ただ、IBOutletの宣言部分はUIパーツとつなげれば、自動で記述されるものですから、そこでのOptionalの指定がおかしいと言われてしまうと、初心者に毛が生えた状態の私ではお手上げになってしまいます。

そこで、もう少し調べてみると、IBOutletに関する情報がのっている記事に行き着きました。

Xcode6 Beta4 でアクセス修飾子がきた!

どうやらIBOutletでも、nilが設定されていることはあるとのことでした。

そして、それはStoryBoardからコネクションが貼られていないなど、いくつかパターンがあるようです。

つまりは、IBOutletが問題ではなく、Viewなどの呼び出し方が問題で結果的にIBOutletでnilが設定されて、エラーになったというのが問題の捉え方としては正しそうです。

となると、呼び出し部分しか思い当たる節がありません。

そこで、前のアプリのソースを引っ張り出して、参照してみたら。

呼び出し方違うじゃんーーーー!!(白目)

間違っていた画面遷移の方法

最初の上記サイト様では、次の画面のViewをpresentViewControllerメソッドで記述しています。

self.presentViewController(mySecondViewController, animated: true, completion: nil)

ですが、これはIBOutletを使わず、NavigationControllerも使わないで呼び出すやり方になります。

どうやら、このやり方で呼び出すとStoryBoardとのコネクションがとれずに、IBOutleにnilが設定されるようです。

ほんとはこうすべきだったんですね。

//次の画面に遷移する。
performSegueWithIdentifier("secondview_segue", sender: nil)

このメソッドを使って画面遷移するには、最初のViewと次のViewをつなげて、該当のStoryboard SegueのIdentiferに値を設定しておく必要があります。(上記の場合は、「secondview_segue」がIdentiferの値です。)

また、NavigationControllerも設定しておきましょう。

Navigation Controllerの追加方法

swiftで画面遷移:UINavigationController

ということで、設定したら問題なく画面遷移ができました。

急いては事を仕損じる。

今回は恥を忍んで、勘違いした部分も書いています。

今思い返すと、なんでそんな勘違いをするの!?と思うのですが、当時はSwiftがあって、iOS8があって、Xcodeも変わってと、よくわからない事が多すぎて、訳がわかっていなかったなと改めて思います。

ともあれ、焦りは禁物です。

今回もムキーッ!となることが多々ありましたが、そういった焦りの状態の場合、視野が狭くなってしまい、解決に時間がかかることが多かったです。

エラーになったらエラーになったで、ブログに書くネタができた!くらいに思いながら、じっくりとことに取り組んだ方が賢明のようですね。

 - Swift, Xcode, アプリ