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

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

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

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1806閲覧

Swift3でSwiftyJSONとAlamofireを用いてAPI通信によって天気し、特定の画像を画面に表示させたい

TaigaMikami

総合スコア20

Swift

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2017/05/14 06:50

###前提・実現したいこと
天気APIで天気情報を取得したときに、天気によってImageViewの画像を更新したい。
天気APIで天気を取得することはできています。

###発生している問題・エラーメッセージ
下記のWeatherViewControllerでのコメントとなっているボタンActionのcheckButtonTappedを使用するとImageViewの画像の更新は行えるが、ボタンを使用せず、Viewのロードで画像の更新をしようと考え、checkWeather()に置き換えてみると画像が更新されません。

###該当のソースコード

Swift

1import UIKit 2 3class WeatherViewController: UIViewController { 4 5 @IBOutlet weak var weatherImage: UIImageView! 6 @IBOutlet weak var tempLabel: UILabel! 7 8 // APIリクエストや、レスポンスデータを利用するためのクラスのインスタンス 9 let dataManager = WeatherDataManager() 10 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 14 // Do any additional setup after loading the view. 15 16 // ここでAPIリクエストを行う 17 self.dataManager.dataRequest() 18 19 checkWeather() 20 } 21 22 23 24 // MARK: Functions 25 func checkWeather() { 26 // お天気APIの返却値によって画像を変更する条件式 27 if dataManager.weatherData?.weather == "Clouds" { 28 // 曇 29 weatherImage.image = UIImage(named: "cloud") 30 } else if dataManager.weatherData?.weather == "Clear" { 31 // 晴れ 32 weatherImage.image = UIImage(named: "sunny") 33 } else if dataManager.weatherData?.weather == "Rain" { 34 // 雨 35 weatherImage.image = UIImage(named: "rain") 36 } 37 38 // 気温ラベルに気温をセット 39 tempLabel.text = dataManager.weatherData?.temp.description 40 41 print("in!in!in!") //関数が実行されているかの確認 42 } 43 44 45 // MARK: Action 46 // あとで消す 47 @IBAction func backAlarmPage (_sender: AnyObject){ 48 //現在のシーンを閉じてアラーム設定ページに戻る 49 self.dismiss(animated: true, completion: nil) 50 } 51 52 // あとで消す 53// @IBAction func checkButtonTapped(_ sender: Any) { 54// // お天気APIの返却値によって画像を変更する条件式 55// if dataManager.weatherData?.weather == "Clouds" { 56// // 曇 57// weatherImage.image = UIImage(named: "cloud") 58// } else if dataManager.weatherData?.weather == "Clear" { 59// // 晴れ 60// weatherImage.image = UIImage(named: "sunny") 61// } else if dataManager.weatherData?.weather == "Rain" { 62// // 雨 63// weatherImage.image = UIImage(named: "rain") 64// } 65// 66// // 気温ラベルに気温をセット 67// tempLabel.text = dataManager.weatherData?.temp.description 68// // ボタンを隠す 69// self.checkButton.isHidden = true 70// } 71 72 73 override func didReceiveMemoryWarning() { 74 super.didReceiveMemoryWarning() 75 // Dispose of any resources that can be recreated. 76 77 } 78 79} 80

Swift

1import Foundation 2 3 4// 必要なフレームワークをインポートする 5import Alamofire 6import SwiftyJSON 7 8// AlamofireによるAPI通信を管理 9class WeatherDataManager: NSObject{ 10 11 // レスポンスデータをパースするモデルクラスのインスタンスを格納すプロパティ 12 var weatherData: WeatherDataModel? 13 14 // リクエストするurl 15 let url = "http://api.openweathermap.org/data/2.5/forecast?units=metric&q=Tokyo&APPID=2ec06eb3d8b93310aa2773a10f1dafe4" 16 17 // APIリクエストを実行する 18 func dataRequest() { 19 20 // AlamofireによるAPI通信 21 Alamofire.request(url).responseJSON { response in 22 switch response.result { 23 24 case .success(let value): 25 // 通信成功時の処理 26 // レスポンスデータをJSON型に変換する 27 // これはSwiftyJSONのルール 28 let json = JSON(value) 29 // JSONデータを引数に渡してモデルクラスのインスタンスを生成 30 self.weatherData = WeatherDataModel(data: json) 31 // デバッグ用のログ出力を行う 32 print(value) 33 34 case .failure(let error): 35 // 通信失敗時の処理 36 // ログ出力だけ 37 print(error) 38 } 39 } 40 } 41} 42

Swift

1import Foundation 2 3// 必要なフレームワークをインポートする 4import SwiftyJSON 5 6class WeatherDataModel: NSObject{ 7 8 // 今日の天気(晴れ、雨etc)を格納するプロパティ 9 var weather: String = "" 10 11 // 気温を格納するプロパティ 12 var temp: Int = 0 13 14 //weatherDataManagerクラスから初期化される 15 init?(data: JSON){ 16 17 //引数で渡ったJSONデータをここでパースする 18 //パース:JSONデータをプロジェクト内で使えるようにする 19 //今日の天気データを取得して変数に格納する 20 self.weather = data["list"][0]["weather"][0]["main"].stringValue 21 self.temp = data["list"][0]["main"]["temp"].intValue 22 } 23} 24

###補足情報(言語/FW/ツール等のバージョンなど)
Xcode8.3.1,Swift3

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

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

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

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

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

guest

回答1

0

ベストアンサー

更新されないのは、Alamofire.request(url).responseJSON が非同期処理で、checkWeather()が呼ばれるときには未だ通信が終わっていないからです。
checkWeather()の直後にprint("hogehoge")でもして確かめてみてください。

解決策としてはWeatherDataManagerWeatherViewControllerへの参照をもたせ、通信が終わったらcheckWeather()を呼んでやればいいかと思います

追記:
適当ですが、こんな感じでしょうか

swift

1class WeatherDataManager: NSObject{ 2 var delegate: WeatherViewController? 3 .... 4 delegate?.checkWeather() 5 print(value)

swift

1override func viewDidLoad() { 2 super.viewDidLoad() 3 self.dataManager.delegate = self 4}

投稿2017/05/14 07:47

編集2017/05/14 08:54
TakeoAsai

総合スコア880

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

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

TaigaMikami

2017/05/14 08:40 編集

回答ありがとうございます。 「checkWeather()」の直後に「print("hogehoge")」挿入し確認してみるとhogehogeの表示を確認できましたが、JSONのデバッグログより先に出力していました。これが「checkWeather()」が呼ばれるときにはまだ通信が終わってないと言うことで合っていますか? また、「WeatherDataManager」に「WeatherViewController」への参照をもたせるとは具体的に何をすればよいか教えていただければ嬉しいです。
TakeoAsai

2017/05/14 08:54 編集

> まだ通信が終わってないと言うことで合っていますか? あっています。 > 具体的に何をすればよいか教えていただければ嬉しいです。 追記しました
TaigaMikami

2017/05/14 09:01

回答ありがとうございます。 お手数おかけしてすみません。理想通りの動作が確認できました。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問