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

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

ただいまの
回答率

90.53%

  • Swift

    8559questions

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

APIからJSONで取得した文字をStoryboardに出力できない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 654
退会済みユーザー

退会済みユーザー

APIからJSONで取得した文字をStoryboardに出力できないです。

import Foundation

import Alamofire
import SwiftyJSON

class WeatherDataManager: NSObject {
    var weatherData: WeatherDataModel?
    let url = "http://api.openweathermap.org/data/2.5/forecast?units=metric&q=Tokyo&APPID=2ec06eb3d8b93310aa2773a10f1dafe4"

    func dataRequest() {
        Alamofire.request(url).responseJSON { response in
        switch response.result {
        case .success(let value):
            let json = JSON(value)
            self.weatherData = WeatherDataModel(data: json)
            print(value)
        case .failure(let error): break 
        print(error)
        }
    }
}
}


とコードを書いて、print(value)でJSONでのレスポンスの正常な結果が得られました。
Main.storyboardに連結したViewControllerに

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var weatherImage: UIImageView!

    @IBOutlet weak var tempLabel: UILabel!

    @IBOutlet weak var checkButton: UIButton!

    let dataManager = WeatherDataManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataManager.dataRequest()
    }

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

    @IBAction func checkButton(_ sender: Any) {
        if dataManager.weatherData?.weather == "Clouds" {
            weatherImage.image = UIImage(named: "cloud")
        } else if dataManager.weatherData?.weather == "Clear" {
            weatherImage.image = UIImage(named: "sunny")
        } else if dataManager.weatherData?.weather == "Rain" {
            weatherImage.image = UIImage(named: "rain")
        }
        tempLabel.text = dataManager.weatherData?.temp.description 
        self.checkButton.isHidden = true 
    }
}


と書いて、tempLabelに得られたJSON結果の

            ・
            ・
            ・
    list =     (
                {
            clouds =             {
                all = 32;
            };
            dt = 1501470000;
            "dt_txt" = "2017-07-31 03:00:00";
            main =             {
                "grnd_level" = "1018.08";
                humidity = 81;
                pressure = "1018.08";
                "sea_level" = "1021.94";
                temp = "29.64";
                "temp_kf" = "0.74";
                "temp_max" = "29.64";
            ・
            ・
            ・


のtemp = "29.64" の29.64を表示させたいです。しかし、今何も表示されていません。ViewControllerとtempLabel: UILabel の連結は問題なくできています。それにJSONもうまく取得できているので何が問題なのかわかりません。どう直せば表示されますか?

tempLabel.text = "hogehoge" がラベルに表示されるか確認するためViewControllerには

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var weatherImage: UIImageView!

    @IBOutlet weak var tempLabel: UILabel!

    @IBOutlet weak var checkButton: UIButton!

    let dataManager = WeatherDataManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // ここでAPIリクエストを行う 
        self.dataManager.dataRequest()
    }

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

    @IBAction func checkButton(_ sender: Any) {
        // お天気API 返却値によって画像を変更する条件式
        if dataManager.weatherData?.weather == "Clouds" {
            // 「Clouds」だったら「曇り」 画像を表示する
            weatherImage.image = UIImage(named: "cloud")
        } else if dataManager.weatherData?.weather == "Clear" {
            // 「Clear」だったら「晴れ」 画像を表示する
            weatherImage.image = UIImage(named: "sunny")
        } else if dataManager.weatherData?.weather == "Rain" {
            // 「Rain」だったら「雨」 画像を表示する
            weatherImage.image = UIImage(named: "rain")
        }
        // 気温 ラベルに取得した気温を表示させる
//        tempLabel.text = dataManager.weatherData?.temp.description 
        tempLabel.text = "hogehoge"
        self.checkButton.isHidden = true

    }

}


と書きました。
イメージ説明

ViewControllerとtempLabel: UILabel の連結状態は、
イメージ説明
のようになっています。

WeatherDataModel.swiftには

import Foundation
// 必要なフレームワークをインポートする 
import SwiftyJSON

// SwiftyJSONによるパースを行うクラス 
class WeatherDataModel: NSObject {

    // 今日 天気(晴れ、雨等)を格納するプロパティ 
    var weather: String = ""
    // 気温を格納するプロパティ 
    var temp: Int = 0

    // weatherDataManagerクラスから初期化される 
    init?(data: JSON) {
    // 引数で渡ってきたJSONデータをここでパースする 
    // 今日 天気データを取得して変数に格納する
    self.weather = data["list"][0]["weather"][0]["main"].stringValue
    //気温データを取得して変数に格納する
    self.temp = data["list"][0]["main"]["temp"].intValue
//    print("here")
//    print(data["list"][0]["main"]["temp"])
//    print("here")
//    print(type(of: data))
}
}

ViewControllerのレイアウト画面(Storyboard)は、
イメージ説明
です。
ViewController全体のアウトレット接続状況は
イメージ説明

イメージ説明

です。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2017/07/31 16:13

    tempLabel=(UILabel!) nil と表示されました。なぜnilになってしまうのでしょうか?

    キャンセル

  • fuzzball

    2017/07/31 16:26

    試したコードを書いてみてもらえますか?(何をやっているのかさっぱり分かりません)

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/07/31 16:37

    tempLabel.text = "hogehoge" を追加したコードを記載しました。tempLabel=(UILabel!) nil  は画像の部分で表示されました。

    キャンセル

回答 2

checkベストアンサー

0

デバッグエリアの変数ウインドウ表示から、
weatherImageとcheckButtonはオブジェクトが読み込まれているのに
tempLabelだけがnilなのが謎すぎです。
普通に考えるとtempLabelだけ接続できていないように見えます。

また、コンソールウインドウには
「here」と「29.67」とだけ表示されているのですが、
質問のコードを実行したら、
WeatherDataManagerのprint(value)により
サーバーから受信した大量のデータが表示されるはずです。
それらが表示されず「here」と「29.67」とだけ
表示されているのが謎すぎです。
普通に考えると質問のコードと違うコードが実行されているように見えます。

デバッグエリアに表示されている情報は、
本当に質問のコードとアウトレット接続の状態を
実行した結果なのでしょうか?

問題が発生する状況の
・ViewControllerのレイアウト画面(Storyboard)
・ViewController全体のアウトレット接続状況
(StoryboardでViewControllerを選択してConnection Inspectorを表示)
・ViewControllerのソースコード
・WeatherDataManagerのソースコード
・WeatherDataModelのソースコード
一式全部見せてもらえば、こちらでも同じ状況を再現させて
比較してみることもできると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/08/01 10:06

    5点の情報の追加を行いました。もしお分かりでしたらお願いします。

    キャンセル

  • 2017/08/01 10:20 編集

    情報追加ありがとうございます。
    StoryBoardのレイアウト画面を貼ってもらってすぐわかりました。
    画面を2つ作っていて、どちらにも同じViewControllerを使用しているのですね。
    これが問題の原因です。

    1つめの画面にはweatherImageとcheckButtonしかありません。
    その画面にはtempLabelが存在しないのに、1つめの画面のcheckButtonの
    動作で2つめの画面のtempLabelにアクセスしようとするからエラーになるのです。

    1つめの画面と2つめの画面で別々のビューコントローラークラスを作り、
    それぞれの画面に割り当ててください。それが問題解決の第一歩です。

    そして、ボタンをタップしたら2つめの画面に遷移するようにしてください。
    あとは、2つめの画面に遷移する時に1つめの画面で取得した情報を2つめの画面に
    引き渡し、2つめの画面の初期化処理でweatherImageとtempLabelに天気の情報を
    設定してください。

    今説明したことをやるのにどうしたらいいのかわからないのでしたら、入門レベルの
    勉強が必要ですので、iPhoneアプリ開発の入門書を買って読んでください。
    今やろうとしていることは画面遷移の基本中の基本です。

    キャンセル

0

ViewControllerとtempLabel: UILabel の連結は問題なくできています

出来ていないと思われますので、もう一度確認して下さい。
なぜ「出来ている」と思うか書いてもらえるとアドバイス出来るかも知れません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/31 17:19

    Mainstoryboardのインスペクタの画像を質問に追加しました。連結ができていると思うのですが。。。

    キャンセル

  • 2017/07/31 17:44

    ViewController()はどうやって生成しているのでしょうか?
    Initial View Controllerですか?

    キャンセル

  • 2017/07/31 20:20

    ViewControllerのインスタンス作成ViewController()はどこにも存在していません。貼り付けたコード以外は何も書いていないので...。

    キャンセル

  • 2017/07/31 23:10 編集

    ・viewDidLoad()で print(tempLabel) を追加して出力を教えて下さい。
    ・checkButton()の冒頭にあるif文を全てコメントアウトして試して下さい。

    キャンセル

  • 2017/08/01 09:50

    viewDidLoad()で print(tempLabel) を追加した出力は、
    fatal error: unexpectedly found nil while unwrapping an Optional value
    と出てエラーで落ちてしまいました。
    Thread 1:EXC_BAD_INSTRUCTION(code=EXC_l386_INVOP,subcode=0x0)とエラーが出ました。

    キャンセル

  • 2017/08/01 09:52

    checkButton()の冒頭にあるif文を全てコメントアウトして実行すると、fatal error: unexpectedly found nil while unwrapping an Optional valueとエラーが出ました。Thread 1:EXC_BAD_INSTRUCTION(code=EXC_l386_INVOP,subcode=0x0)と同じエラーが出ました。

    キャンセル

  • 2017/08/01 10:03

    それぞれどこで落ちているのでしょうか?
    最初の方は、print(tempLabel) が出力されていないのでしょうか?

    キャンセル

  • 2017/08/01 10:10

    最初の方では、
    print(tempLabel)は出力されていません。print(tempLabel)の行で落ちていました。
    checkButton()の方では、
    tempLabel.text = "hogehoge" のところで落ちていました。

    キャンセル

  • 2017/08/01 10:13

    追加された画像で、上の画像が右側のViewControllerなのであれば、tempLabelは接続されていないことになりますが?

    キャンセル

  • 2017/08/01 10:22

    右側の画像の”ここでチェック!”ボタンを押すと、左側の現在のお天気画面が出て気温が表示され、@IBAction func checkButton(_ sender: Any)が呼ばれその時の天気ごとに画像が変わる仕様にしたいのですが、それができていないということでしょうか?

    キャンセル

  • 2017/08/01 10:33

    画面遷移に関して言えば、Storyboard上でも繋がっていないし、遷移させるコードも無いし、遷移するわけがありません。
    今回の場合はそれ以前の問題ですので、TakeOneさんのコメントを読んでがんばって下さい。

    キャンセル

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

  • Swift

    8559questions

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