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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

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

Q&A

解決済

2回答

2193閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

Swift

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

0グッド

0クリップ

投稿2017/07/31 02:05

編集2017/08/01 01:06

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全体のアウトレット接続状況は
イメージ説明

イメージ説明

です。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/07/31 02:49

tempLabel.text = "hogehoge" でラベルに表示されますか? dataManager.weatherData はnilではないですか?
退会済みユーザー

退会済みユーザー

2017/07/31 02:50

それはどのようにして確認できますか?
fuzzball

2017/07/31 02:54

後半の質問でしたら print(dataManager.weatherData)で確認して下さい。
退会済みユーザー

退会済みユーザー

2017/07/31 04:57

はい。fatal error: unexpectedly found nil while unwrapping an Optional value (lldb) と nilと言われました。何が原因なのでしょうか?
fuzzball

2017/07/31 05:06 編集

WeatherDataModel(data:)のdataはData型でしょうか? Data型でしたら print(json.count) の出力を教えて下さい。Data型でなければ型を教えて下さい。
退会済みユーザー

退会済みユーザー

2017/07/31 05:22

print(type(of: data)) で調べたら、型はJSONであると言われました
fuzzball

2017/07/31 05:40

最初の質問の前半の結果はどうでしたか? また、let json = JSON(value) の次に行に print(json) を追加してnilかどうかチェックして下さい。nilでなければ、さらに print(data["list"][0]["main"]["temp"]) を追加して出力を教えて下さい。
退会済みユーザー

退会済みユーザー

2017/07/31 05:52

すみません、tempLabel.text = "hogehoge" でラベルに表示されますか? の意味がわからず...。どのように確認できますか?
退会済みユーザー

退会済みユーザー

2017/07/31 05:56

let json = JSON(value) の次の行の print(json)はnilではありませんでした。(取得したいjsonが取得できていました)
退会済みユーザー

退会済みユーザー

2017/07/31 05:56

print(data["list"][0]["main"]["temp"])では 31.73 と出力され、取得したいものが取得できていました。
fuzzball

2017/07/31 06:00 編集

「どのように確認できますか?」ですが、画面上のラベルに表示されるか?という意味です。ラベルの表示がおかしいのであれば、何をやっても表示されるわけはありません。(一番最初に確認すべき項目です)
退会済みユーザー

退会済みユーザー

2017/07/31 06:36

質問文に、tempLabel: UILabelのIDなどの情報のインスペクタの情報の画像を追加しました。もしかしたら必要なものが空かもしれません...。
fuzzball

2017/07/31 07:06

tempLabel.text = dataManager.weatherData?.temp.description の代わりに tempLabel.text = "hogehoge" にして、ラベルに hogehoge と表示されるか?ということです。画像は必要ないので削除して下さい。
退会済みユーザー

退会済みユーザー

2017/07/31 07:13

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

2017/07/31 07:26

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

退会済みユーザー

2017/07/31 07:37

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

回答2

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/07/31 22:55

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/08/01 01:06

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

2017/08/01 01:23 編集

情報追加ありがとうございます。 StoryBoardのレイアウト画面を貼ってもらってすぐわかりました。 画面を2つ作っていて、どちらにも同じViewControllerを使用しているのですね。 これが問題の原因です。 1つめの画面にはweatherImageとcheckButtonしかありません。 その画面にはtempLabelが存在しないのに、1つめの画面のcheckButtonの 動作で2つめの画面のtempLabelにアクセスしようとするからエラーになるのです。 1つめの画面と2つめの画面で別々のビューコントローラークラスを作り、 それぞれの画面に割り当ててください。それが問題解決の第一歩です。 そして、ボタンをタップしたら2つめの画面に遷移するようにしてください。 あとは、2つめの画面に遷移する時に1つめの画面で取得した情報を2つめの画面に 引き渡し、2つめの画面の初期化処理でweatherImageとtempLabelに天気の情報を 設定してください。 今説明したことをやるのにどうしたらいいのかわからないのでしたら、入門レベルの 勉強が必要ですので、iPhoneアプリ開発の入門書を買って読んでください。 今やろうとしていることは画面遷移の基本中の基本です。
guest

0

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

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

投稿2017/07/31 07:50

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/07/31 08:19

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

2017/07/31 08:44

ViewController()はどうやって生成しているのでしょうか? Initial View Controllerですか?
退会済みユーザー

退会済みユーザー

2017/07/31 11:20

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

2017/08/01 00:34 編集

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

退会済みユーザー

2017/08/01 00: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 00:52

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

2017/08/01 01:03

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

退会済みユーザー

2017/08/01 01:10

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

2017/08/01 01:13

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

退会済みユーザー

2017/08/01 01:22

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

2017/08/01 01:33

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問