【Xcode】モーダル表示で遷移先へ値を渡す時のハマりポイント

公開日: : iPhoneアプリ開発

20160210-140020.jpg

モーダル表示で遷移先の画面へ値を渡す際、最初はハマりやすいポイントについて解説したいと思います。

    

スポンサード リンク

例えば、以下のような画面遷移を考えたとします。

20160210-140327.jpg

1つ目の画面でテキストフィールドに文字を入力してボタンを押すと、モーダル表示で次の画面に遷移し、入力した文字がラベルに表示されるという動きです。

    

1つ目の画面では、prepareForSegueで次の画面に入力テキストを受け渡します。

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        guard let second = segue.destinationViewController as? SecondViewController else {
            return
        }

        guard let text = self.textField.text else {
            return
        }
        
        second.text = text
    }
}

    

そして2つ目の画面ではviewDidLoadにて、前の画面から受け渡されてきた入力テキストをラベルに表示します。

class SecondViewController: UIViewController {
    
    var text : String = ""

    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.label.text = text
    }
}

    

これでうまく動きそうですが、実行してみると2つ目の画面のラベルに何も表示されません。

なぜでしょうか?

    

1つ目の画面のprepareForSegueに以下のコードを追加してみましょう。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    // 追加。destinationViewControllerの中身の型を調べる
    print("type = \(segue.destinationViewController.dynamicType)")
    
    guard let second = segue.destinationViewController as? SecondViewController else {
        return
    }

    guard let text = self.textField.text else {
        return
    }
    
    second.text = text
}

    

ちなみにdynamicTypeを使うと、インスタンスが実際に属するクラスを表すオブジェクトを得ることができます。

インスタンスに対してdynamicTypeという問い合わせを行うと、実際に属するクラスを表すオブジェクト(便宜的にクラスオブジェクトと呼びます)を値として得ることができます。

引用元 : 詳解 Swift 改訂版

    

そして再び実行すると、1つ目の画面でボタンをタップした際に以下のような出力がなされます。

type = UINavigationController

なんと、destinationViewControllerの中身がSecondViewControllerではなくてUINavigationControllerになっています!

    

これは何故かというと、1つ目の画面からUINavigationControllerに対してセグエを接続しているからなんですね。

20160210-142431.jpg

だから最初の

guard let second = segue.destinationViewController as? SecondViewController else {
    return
}

でas?によるダウンキャストに失敗して、次の画面にデータが受け渡されなかったわけです。

    

なので、1つ目の画面のprepareForSegueでは

  • まずセグエで接続されているUINavigationControllerを取得する
  • 次に、UINavigationControllerにぶら下がっているSecondViewControllerを取得する

という2段階の手順を踏まなければならないわけです。

これに従ってコードを書いてみましょう。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    // まずセグエで接続されているUINavigationControllerを取得する
    guard let nav = segue.destinationViewController as? UINavigationController else {
        return
    }
    
    // UINavigationControllerにぶら下がっているSecondViewControllerを取得する
    guard let second = nav.topViewController as? SecondViewController else {
        return
    }

    guard let text = self.textField.text else {
        return
    }
    
    second.text = text
}

これで無事、2つ目の画面に入力テキストが表示されるようになります!

    

@akio0911はこう思った。

今日解説した部分は、入門書などを読みながら学習していく過程でハマりやすいポイントの1つだと思います。

    

ちなみに解説の中で出てきた「guard」「as?」などについては、以下の本が詳しいです!

この記事が気に入ったら「いいね!」しよう

follow us in feedly

Feedlyで最新記事を購読

Twitterで更新情報をゲット!

LINEでご感想・ご要望お送りください!
(スマホでLINEを起動 > 友だち追加 > QRコード)

関連記事

20150525-224340.jpg

【Swift】クロージャをメソッドや関数の引数として渡す方法

Swiftでメソッドの引数としてクロージャを渡す方法について解説したいと思います。     

記事を読む

I20151119-165939.jpg

Swift 2.1に対応した本「詳解 Swift 改訂版」が出るぞ!

Swiftの文法に関する解説書の定番「詳解 Swift」の、Swift2.1に対応した改訂版「詳

記事を読む

20141210-164612.jpg

【Swift】Generated Header内にSwiftクラスの定義が記述されない場合の確認事項【Xcode6】

Swiftで書いたクラスをObjective-Cで使う際には、「Generated Header

記事を読む

20140724-103334.jpg

iPhoneアプリ開発にオススメの本10選(2014年7月版)

@akio0911です。2013年12月に「レベル・目的別!iPhoneアプリ開発おすすめ本

記事を読む

I20160918-133158.jpg

StoryboardでChild View Controllerにデータを渡す方法(Xcode 8 & Swift 3)

Storyboardで、Child View Controllerにデータを渡す方法を紹介します

記事を読む

20160807-113229.jpg

UITableViewのリサイズに合わせて一番下のセルを常に一番下に表示する方法

一番下のセルを表示している状態でUITableViewの下端を上に移動させると一番下のセルが隠れ

記事を読む

20140807-182914.jpg

【アプリ開発】iOS 8とiOS 7でUIAlertController・UIAlertView・UIActionSheetを切り替えて使う方法

@akio0911です。今までお世話になったUIAlertViewとUIActionShee

記事を読む

I20160126-141427.jpg

Swift 2でtoIntが使えない!unavailableエラーが出た時の対処方法

Swift 2でtoInt()を使うと、 'toInt()' is unavailable:

記事を読む

I20160208-152320.jpg

【Swift】privateなタイプメソッド作るなら、privateな関数でも良いかもと思った

structとかclassの中で、ちょっとした処理を担当させるprivateなタイプ

記事を読む

20160508-170745.jpg

SwiftTaskで失敗したタスクによって異なるエラー処理を行う方法

SwiftTaskで複数のタスクを.successでチェーンさせ、失敗したタスクによって

記事を読む

I20170521-225453.jpg
東京駅八重洲口の「羊肉酒場 悟大」で網焼きジンギスカンを頂きました!

ゆうせいさんと株式会社 大庄さんからご招待頂き、悟大withサッポ

I20170514-165235.jpg
iPhoneと連携できる体重体組成計「Withings Body Cardio」を使ってます

ジムに通い始めて体脂肪率が落ち始めたのをキッカケに、iPhoneと

I20170507-155440.jpg
【派手髪】ハーレイクイン風の髪色に染めてもらいました

2016年10月20日、ハーレイクイン風の髪色に染めてもらいました

I20170504-173110.jpg
【メンズネイル】東京・新宿のネイルサロンでターコイズのホログラムネイルしてもらった

ネイルネタが1年分くらい溜まっているので、ちょっとずつ書いていこう

I20170502-010117.jpg
SNUGGのライトニングケーブルが耐久性高し。8ヶ月使ってますが断線の気配なし!

iPhoneの充電&転送ケーブルであるLightningケーブルっ

→もっと見る

PAGE TOP ↑