質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • Swift

    7687questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4348questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

【Swift】画面遷移時の値引き継ぎ

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,702

Ruthi

score 53

前提・実現したいこと

Xcode8.0/Swift3で簡易的なBMI値の計算アプリを作っています
入力画面で身長、体重、年齢の値を入力、計算ボタンを押すと計算し、BMI値や肥満度など複数の結果を結果画面の変数に代入
結果画面へ引き継ぎを行い、遷移して結果表示という処理を行いたいのですが、変数の引き継ぎに関する部分がなかなか上手くできません

ボタンを押した時に値が正しく入力されていなかったり、入力された値が極端に小さい、大きい場合は画面は遷移せずエラーメッセージを出すようにしたいので
ボタンを押した時の@IBAction内に記述することで画面遷移と変数の引き継ぎ処理を行っています

発生している問題・エラーメッセージ

計算ボタンを押した時、画面は遷移するが結果画面の答えを表示するラベルには反映されない

該当のソースコード

    FirstViewController.Swift

    @IBAction func Calculation(_ sender: Any) {
        //テキストフィールドに入力された身長と体重の値をfloat型に変換
        let height:Float? = Float(Textheight.text!)
        let weight:Float? = Float(Textweight.text!)
        let age:Int? = Int(Textage.text!)

        //追記箇所
        //身長もしくは体重に何も入力されていない場合(エラー)
        if height == nil || weight == nil
        {
            Error.text = "正常に値が入力されていないため\n計算できません。\n再入力してください。"
        }

        //身長が80cm以下or220cm以上、体重が20kg以下or300kg以上(異常数値を弾く処理)
        else if height! <= 80 || height! >= 220 || weight! <= 20 || weight! >= 300{
            Error.text = "規定の範囲外のため\n計算できません。\n再入力してください。"
        }

        //後々結果画面のテキストへ代入するBMI値や肥満度を代入する変数の宣言
        var Ca:String!
        var St:String!
        var Ad:String!
        var StWe:String!
        var Id:String!
        var Me:String!

        //
        //入力された身長、体重などからBMI値の計算処理を行うプログラム
        //(今回の内容には特に関係ないため省きます)
        //この処理の中で上記で宣言してあるCaやStに算出されたBMI値等を代入しています
        //

         present(SecondViewController, animated: true, completion: nil)

        }
        //SecondViewControllerの
        override func prepare(for segue: UIStoryboardSegue, sender: Any?){
        let Second = segue.destination as! SecondViewController
        //BMI値等算出された値を渡す
        Second.Cal = Ca
        Second.Sta = St
        Second.Adv = Ad
        Second.StaWei = StWe
        Second.Ide = Id
        Second.Met = Me
    }
    SecondViewController.Swift

    import UIKit

class SecondViewController: UIViewController {

    //UIラベルの設定
    //をここで行っています

    //ViewControllerから受け取る変数
    var Cal = ""
    var Sta = ""
    var Adv = ""
    var StaWei = ""
    var Ide = ""
    var Met = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        //ラベルにFirstViewControllerから受け取った値を表示
        CalculationResult.text = Cal
        Standard.text = Sta
        Advice.text = Adv
        StandardWeight.text = StaWei
        Ideal.text = Ide
        MetabolismStandard.text = Met

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

補足情報(言語/FW/ツール等のバージョンなど)

冒頭でも述べた通り
Xcode8.0
Swift3
で作っています

Swiftを触り始めてまだほんの少ししか経っておらず粗だらけのプログラムですがどうかご教授のほどよろしくお願い致します

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

prepare(for:​sender:​)をCalculation(_:)の外に出して、

//画面の遷移
let storyboard: UIStoryboard = self.storyboard!
let nextView = storyboard.instantiateViewController(withIdentifier: "SecondView")
present(nextView, animated: true, completion: nil)

//画面の遷移
present(SecondViewController, animated: true, completion: nil)
//※遷移するViewControllerは新たに生成するのではなくセグエで渡されたものを使う

に変更して下さい。

※SecondViewControllerという変数名はクラス名と同じで紛らわしいので変えた方がいいです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/13 16:01

    回答ありがとうございます。
    Calculation(_:)の外に出すとなるとボタンが押下された際の処理から外れ、値の引き継ぎが行われないまま遷移してしまうのではないかと思うのですが違うのでしょうか?

    変数名は変更致します、ありがとうございます。

    キャンセル

  • 2017/04/13 16:17

    prepare(for:​sender:​)は、遷移する直前に呼ばれます。
    そもそも今は、prepare(for:​sender:​)は実行されていないと思いますが。(中にprint文を入れて確かめてみて下さい)

    キャンセル

  • 2017/04/13 16:36

    prepare(for:​sender:​)の仕様については知りませんでした…ありがとうございます。
    確かに実行されていませんでした、画面の遷移だけは動いていたので混同していたみたいです。

    //遷移するViewControllerは新たに生成するのではなくセグエで渡されたものを使う
    ここの部分が分からないのですが、StoryBoard上でFirstViewControllerからSecondViewControllerへセグエを伸ばすのとは違う手法があるということですか?

    キャンセル

  • 2017/04/13 16:41 編集

    「StoryBoard上でFirstViewControllerからSecondViewControllerに伸ばしたセグエ」がprepare(for:​sender:​)に渡されます。そこから取り出したもの(segue.destination)が、これから遷移するViewControllerです。

    あなたも、値を引き継ぐためにそのViewControllerに値をセットしているじゃないですか。

    キャンセル

  • 2017/04/13 17:34

    セグエ作ってるなら、performSegueメソッドでもいいんじゃないですか。画面遷移。

    キャンセル

  • 2017/04/13 17:36

    調べ直して少々理解が追いついて来ましたが、「Cannot convert value of type 'SecondViewController.Type' to expected argument type 'UIViewController'」というエラーが出ます。
    わざわざお教えいただいたのに申し訳ありません、もう少し格闘してきます。

    キャンセル

  • 2017/04/13 17:38

    >fromageblanc氏
    ありがとうございます、調べて来ます。

    キャンセル

  • 2017/04/13 17:51

    @Ruthiさん
    質問内のコードを現状のものに更新し、どこでエラーが出ているのか書いて下さい。

    キャンセル

  • 2017/04/14 09:18

    お返事遅れ申し訳ありません。
    コードを更新いたしました。
    お教えいただいた
    present(SecondViewController, animated: true, completion: nil)のSecondViewConrtollerからエラーが出ています。
    SecondViewConrtollerの部分をStoryboard ID等いろいろ思い当たるものに書き換えを行ってもほぼほぼ同一の結果となりました。

    エラー内容を調べたのですがTypeA(この場合はSecondViewController)をTypeB(この場合はUIViewController)に変換できない?という旨の解説が出てきました

    キャンセル

  • 2017/04/14 09:40 編集

    最初の方に書いた変数SecondViewControllerの名前を変更して下さい。

    キャンセル

  • 2017/04/14 09:56

    申し訳ありません、記入漏れです。
    変数SecondViewControllerは現在Secondという名前になっております。コードもそのように修正し直しました。

    キャンセル

  • 2017/04/14 10:06

    いつの間にかpresent(...)がCalculation(_:)の中に移動していますが、これは不要なので削除して下さい。
    (ちなみにpresent(...)内のSecondViewControllerは変数名なので、現在ならSecondになります。紛らわしいでしょ?)

    一旦これでどうなるか試して下さい。

    キャンセル

  • 2017/04/14 10:31

    質問当初の目的が「ボタンが押された時に計算、変数引き継ぎ、画面遷移を行いたい」なので最初からCalculation(_:)の中にpresent(...)はいたはずなのですが、必要ないのですか?
    (念のため削除する前にpresent(...)内のSecondViewControllerをSecondに変えてみましたが、prepare(for:sender:)がCalculation(_:)の外にいるからか定義されていないというエラーが出ました)

    presentを削除するとエラーは消えましたが正常な値を入力した上で計算ボタンを押しても画面は遷移しなかったです
    ViewControllerからセグエを伸ばしているので当然かもしれませんが……

    キャンセル

  • 2017/04/14 10:35

    今あるセグエはFirstViewControllerとSecondViewControllerを繋いでいるManualなセグエだと思うので、これを削除し、ボタンとSecondViewControllerをセグエで繋いで下さい。

    キャンセル

  • 2017/04/14 10:55

    ボタンと繋いだら正常に画面が遷移し、遷移先の画面で正しい計算結果が表示されるのを確認できました、ありがとうございます!
    しかし現状だと入力画面で身長、体重、年齢の値に何も入力されていない等のエラーメッセージが表示されるはずの状態(一応質問のコードにエラーメッセージ表示部分を追記しました)であっても、計算ボタンを押すと問答無用で画面が遷移してしまいます
    (これを経験したのでFirstViewControllerからセグエを伸ばす方法に切り替えたのですが逆にダメだったのですね)

    これに関してプログラムで制御する方法はあるのでしょうか?
    以前インターネットで調べた時は「アプリ側で遷移を制御したい場合はViewControllerから伸ばすと良い」というような記述を見たので……

    キャンセル

  • 2017/04/14 10:55

    制御する方法があるかないか、という点だけでも教えていただけると助かります。

    キャンセル

  • 2017/04/14 11:04

    >>エラー処理
    あー、そうですね。すみません。ボケてました。

    セグエは元のManualセグエに戻して下さい。
    で、fromageblancさんがコメントされているように、performSegue(withIdentifier:sender:)でセグエを発動して下さい。(エラーが無かったときだけ)

    キャンセル

  • 2017/04/14 11:18

    performSegue(withIdentifier:sender:)で実行したらエラーのある時は遷移せずメッセージ表示、エラーのない時は遷移して結果表示という望んだ通りの動きができました!
    prepare(for:​sender:​)が遷移直前に呼ばれるという点等これまで知らなかったことまで教えていただいて非常に助かりました。

    何度も質問で返したり無知を晒したりとお見苦しいところをお見せして申し訳ありませんでした。
    fuzzballさん、fromageblancさんこの度は本当にありがとうございました!

    キャンセル

同じタグがついた質問を見る

  • Swift

    7687questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4348questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。