14
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

お天気APIを叩こう!(Swift・OpenWeatherMap)

Last updated at Posted at 2021-04-26

#はじめに
今回は、SwiftでOpenWeatherMapというAPIを叩いて指定した緯度経度の天気情報を取得し、天気情報を表示させようと思います。
この記事を読むことで操作を理解し、APIに関する理解を深められたら幸いです。

#用いるAPIの紹介
今回使うAPIは、OpenWeatherMapという無料で世界中の天気予報などの情報を提供してくれる物を使います。
※一部課金が必要な機能もあります。

#完成予想図
今回は、サンプルとしてOpenWeatherMapを用いて取得した天気情報を表示させます。
result2

#初めてOpenWeatherMapを利用する場合
API Keyの取得にはアカウントの作成が必要です。
まだアカウントを作成していない方は、こちらの記事を参考にしてアカウントを作成し、自身のAPIキーを取得してください。
無料天気予報APIのOpenWeatherMapを使ってみる

#APIのやりとりの仕組み
さらっとAPIのやり取りについての仕組みを説明します。
APIの定義はないですが、HTTPプロトコルを用いてネットワーク越しに呼び出すアプリケーション間、システム間のインターフェースのことを指すことが多いです。(下図参照)

特に、欲しいデータを取得するレスポンスと呼ばれるものは主にJSON型で返ってきます。

このJSON型で返ってきたデータから欲しい情報を抜き出して表示させたりすることができます。
今回はさらっとですが詳しく知りたい方はWeb APIとは何なのかを読んでみてください!

#JSONを見てみよう
では、レスポンスのJSON形式で表示されるデータを見てみましょう!
その前に、まずはリクエスト用のクエリを発行する必要があります。

pro.openweathermap.org/data/2.5/forecast/hourly?lat={lat}&lon={lon}&appid={API key}

このURLのappid=というところに、自分のAPI Keyを入力し、lat=lon=のところに天気の情報が欲しい地区の緯度経度を入力します。
そしてクエリの入力をしたURLをブラウザなどに入れてみると、以下のように現在の天気の情報が表示されると思います。

あれ?なんか思ってたのと違いますね汗
ごちゃごちゃしててよくわからないですが実はこれちゃんと取得できています。

これを綺麗にして可視化できるようにGoogle ChromeのJSON View Awesomeという拡張機能を使ってみようと思います!

するとこんな感じに綺麗に表示させることができました!
さらに整理してみると、、?

39個の天気データがあることがわかりました!!
これでJSON型のデータを見ることができました。

#今回使うライブラリの紹介
SwiftでAPIを利用しようとすると操作の意図がわかりにくい複雑なコードが多く、とても大変です。
そこで今回は2つのライブラリを用いることでコードをできるだけシンプルにわかりやすく書いていこうと思います。
今回用いるライブラリは、
SwiftyJSON
少ない記述量で JSONデータを取得でき、また直感的にJSON内 の欲しい値をゲットすることができるライブラリ

Alamofire
ネットワーク通信(http~)をシンプルに記述することができるライブラリ

の二つになります。
cocoapodsでインストールしましょう。

#実際にコードを書いてみよう!!

####①リクエスト(http~)を発行しよう!!
まず最初に、データを取得するためのリクエストURLを作ります。

let text = "https://api.openweathermap.org/data/2.5/weather?lat=\(latitude)&lon=\(longitude)&units=metric&appid=自分の発行したAPIKey"

https://api.openweathermap.org/data/2.5/weather? ・・・発行元が決めてるから変えられない
?lat=\(latitude)&lon=\(longitude)&units=metric ・・・今回は緯度経度をパラメーターとする

今回は、蔵王温泉スキー場の天気を取得しようと思うのでlatitude=38.1705275longitude=140.417219とします。

このtextは、ただのString型であるのでリクエストとして使える型に変換する必要があります。
そこで、

let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

と書くことで、先ほど定義したtextが新たにurlとしてリクエストに使える型に再定義されました。

####②APIコール処理
①で作成したurlを使って実際にAPIのコール処理を実装します。
ここで、先ほどインポートしたライブラリであるAlamofireを用います。

AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in
            switch response.result {
            case .success:
            case .failure(let error):
            }
        }

Alamofireを用いることでAPIコール処理を簡潔に実装できます。
標準と比較した記事はこちら

####③レスポンス後の処理
まずコードを提示します。

 switch response.result {
            case .success:
                let json = JSON(response.data as Any)
                self.descriptionWeather = json["weather"][0]["main"].string!
                self.max.text = "\(Int(json["main"]["temp_max"].number!).description)℃"
                self.min.text = "\(Int(json["main"]["temp_min"].number!).description)℃"
                self.taikan.text = "\(Int(json["main"]["temp"].number!).description)℃"                
                self.wind.text = "\(Int(json["wind"]["speed"].number!).description)m/s"

            case .failure(let error):
                print(error)
            }

まず、天気情報結果を代入している値response.dataをJSONとしてjsonを作成します。
次に解析を行います。
ここで、インポートしたもう一つのライブラリであるSwiftyJSONが役立ちます。
天気だけの情報が欲しい時はjson["weather"][0]["main"].string!のように指定することで値を取得でします。ほんとシンプルでかわかりやすいですよね?

こんな感じでマトリョーシカみたいなイメージで欲しいデータだけを引っ張れます。(この画像は別のプロダクトで撮った写真ですが、、)

####④表示させる
あとは、抽出したデータを煮るなり焼くなりするだけなんでサンプルコードを提示して終わりにしますね!!

import UIKit
import Alamofire
import SwiftyJSON
import KRProgressHUD

class WeatherViewController: UIViewController, UISearchBarDelegate {
    
    @IBOutlet var tenkiImageView: UIImageView!
    @IBOutlet var max: UILabel!
    @IBOutlet var min: UILabel!
    @IBOutlet var taikan: UILabel!
    @IBOutlet var humidity: UILabel!
    @IBOutlet var wind: UILabel!
    @IBOutlet var backImageView : UIImageView!
    
    
    var descriptionWeather: String?
    var cityData : [String] = []
    var selectedCity : String!
    var longitude : Double!
    var latitude : Double!
    
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.addBackground(name: "snow-mountain.jpg")
        

      backImageView.layer.cornerRadius = backImageView.frame.size.width * 0.1
      backImageView.clipsToBounds = true
        tenkiImageView.layer.cornerRadius = tenkiImageView.frame.size.width * 0.1
        tenkiImageView.clipsToBounds = true
        
        yoho()
    }

    func yoho() {
        let latitude = String(self.latitude)
        let longitude = String(self.longitude)
        let text = "https://api.openweathermap.org/data/2.5/weather?lat=\(latitude)&lon=\(longitude)&units=metric&appid=55b317379a06a94f5198e9c297ff0b0e"

        
        let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in
            switch response.result {
            case .success:

                let json = JSON(response.data as Any)

                self.descriptionWeather = json["weather"][0]["main"].string!

                if self.descriptionWeather == "Clouds" {
                    self.tenkiImageView.image = UIImage(named: "kumori")
                }else if self.descriptionWeather == "Rain" {
                    self.tenkiImageView.image = UIImage(named: "ame")
                }else if self.descriptionWeather == "Snow"{
                    self.tenkiImageView.image = UIImage(named: "yuki.gif")
                }else {
                    self.tenkiImageView.image = UIImage(named: "hare")
                }

                self.max.text = "\(Int(json["main"]["temp_max"].number!).description)℃"
                self.min.text = "\(Int(json["main"]["temp_min"].number!).description)℃"
                self.taikan.text = "\(Int(json["main"]["temp"].number!).description)℃"
                self.wind.text = "\(Int(json["wind"]["speed"].number!).description)m/s"
                
            case .failure(let error):
                print(error)
            }
        }
    }
    
}

#終わりに
以上で終わりとなります。
もしかしたら間違いなどがあるかもしれないのであったらご指摘ください。
今回の記事を作成するにあたって
SwiftでAPIを使う! 自分がつまずいたところを詳しく調べてみた
を参考にさせて頂きました。是非こちらもご覧ください。
是非みなさんもお天気表示してみてくださいね!

14
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?