🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Xcode

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

Swift

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

API

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

Q&A

解決済

2回答

1893閲覧

OpenWeatherMapAPIを使って天気情報を取得したい

uma02

総合スコア18

Xcode

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

Swift

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

API

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

0グッド

0クリップ

投稿2020/12/09 03:38

編集2020/12/09 10:06

前提,実現したいこと

openweathermapAPIを使って天気情報を取得しようとしています。
しかし以下のコードだと天気情報を取得できません。
どこが間違っているのでしょうか?
APIに関して初心者で投げやりな感じになってしまい申し訳ないのですがもしわかる方がいらっしゃったらご回答よろしくお願いします。

###発生している問題・エラーメッセージ
エラーメッセージはありませんが、実行するとindicatorが消えない、すなわち天気情報を取得することが出来ません。
ログには以下のように出ます。
2020-12-09 18:51:46.348313+0900 Weather[45340:3150299] screen parameters are unexpected: MGScreenClass1125x2436x3x495 SCREEN_TYPE(1125,2436,3,495)
The operation couldn’t be completed. (kCLErrorDomain error 0.)

###試したこと
breakpointを使いましたが原因は分からなかったです。
ATSの設定も行っております。

またAPIのDocumentを読み直しlat,lonの値を変えてみましたが改善しませんでした。

###参考にしたサイト
https://openweathermap.org/current
https://www.youtube.com/watch?v=WHRntPeAOo4&list=LL&index=1

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

swift

1 2 3import Foundation 4import UIKit 5import Alamofire 6import SwiftyJSON 7import NVActivityIndicatorView 8import CoreLocation 9 10class ViewController: UIViewController, CLLocationManagerDelegate { 11 12 @IBOutlet weak var locationLabel: UILabel! 13 @IBOutlet weak var dayLabel: UILabel! 14 15 @IBOutlet weak var conditionImageView: UIImageView! 16 @IBOutlet weak var conditionLabel: UILabel! 17 18 @IBOutlet weak var temperatureLabel: UILabel! 19 @IBOutlet weak var backgroundView: UIView! 20 21 let gradientLayer = CAGradientLayer() 22 23 let apiKey = "7a4c0ed6b80dbaab6aec67e38968cda3" 24 var lat = 26.8205 25 var lon = 30.8024 26 var activityIndicator: NVActivityIndicatorView! 27 let locationManager = CLLocationManager() 28 29 override func viewDidLoad() { 30 super.viewDidLoad() 31 backgroundView.layer.addSublayer(gradientLayer) 32 33 let indicatorSize: CGFloat = 70 34 let indicatorFrame = CGRect(x: (view.frame.width-indicatorSize)/2, y: (view.frame.height-indicatorSize)/2, width: indicatorSize, height: indicatorSize) 35 activityIndicator = NVActivityIndicatorView(frame: indicatorFrame, type: .lineScale, color: UIColor.white, padding: 20.0) 36 activityIndicator.backgroundColor = UIColor.black 37 view.addSubview(activityIndicator) 38 39 locationManager.requestWhenInUseAuthorization() 40 41 activityIndicator.startAnimating() 42 if(CLLocationManager.locationServicesEnabled()){ 43 locationManager.delegate = self 44 locationManager.desiredAccuracy = kCLLocationAccuracyBest 45 locationManager.startUpdatingLocation() 46 } 47 48 } 49 50 override func viewWillAppear(_ animated: Bool) { 51 setBlueGradientBackground() 52 } 53 54 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 55 let location = locations[0] 56 lat = location.coordinate.latitude 57 lon = location.coordinate.longitude 58 Alamofire.request("http://api.openweathermap.org/data/2.5/weather?lat=(lat)&lon=(lon)&appid=7a4c0ed6b80dbaab6aec67e38968cda3&units=metric").responseJSON { 59 response in 60 self.activityIndicator.stopAnimating() 61 if let responseStr = response.result.value { 62 let jsonResponse = JSON(responseStr) 63 let jsonWeather = jsonResponse["weather"].array![0] 64 let jsonTemp = jsonResponse["main"] 65 let iconName = jsonWeather["icon"].stringValue 66 67 self.locationLabel.text = jsonResponse["name"].stringValue 68 self.conditionImageView.image = UIImage(named: iconName) 69 self.conditionLabel.text = jsonWeather["main"].stringValue 70 self.temperatureLabel.text = "(Int(round(jsonTemp["temp"].doubleValue)))" 71 72 let date = Date() 73 let dateFormatter = DateFormatter() 74 dateFormatter.dateFormat = "EEEE" 75 self.dayLabel.text = dateFormatter.string(from: date) 76 77 let suffix = iconName.suffix(1) 78 if(suffix == "n"){ 79 self.setGreyGradientBackground() 80 }else{ 81 self.setBlueGradientBackground() 82 } 83 } 84 } 85 self.locationManager.stopUpdatingLocation() 86 } 87 88 func locationManager(_ manager: CLLocationManager, 89 didFailWithError error: Error) { 90 print(error.localizedDescription) 91 } 92 93 func setBlueGradientBackground(){ 94 let topColor = UIColor(red: 95.0/255.0, green: 165.0/255.0, blue: 1.0, alpha: 1.0).cgColor 95 let bottomColor = UIColor(red: 72.0/255.0, green: 114.0/255.0, blue: 184.0/255.0, alpha: 1.0).cgColor 96 gradientLayer.frame = view.bounds 97 gradientLayer.colors = [topColor, bottomColor] 98 } 99 100 func setGreyGradientBackground(){ 101 let topColor = UIColor(red: 151.0/255.0, green: 151.0/255.0, blue: 151.0/255.0, alpha: 1.0).cgColor 102 let bottomColor = UIColor(red: 72.0/255.0, green: 72.0/255.0, blue: 72.0/255.0, alpha: 1.0).cgColor 103 gradientLayer.frame = view.bounds 104 gradientLayer.colors = [topColor, bottomColor] 105 } 106 107} 108 109

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

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

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

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

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

guest

回答2

0

自己解決

原因はシミュレータのLocationを設定していないことでした。
Features→Location→customLocationを設定することで解決することができました。
回答してくださった方、本当にありがとうございました。

投稿2020/12/11 13:55

編集2020/12/12 11:53
uma02

総合スコア18

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

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

0

おそらく、ATS の設定を行なっていないことが原因かと思います。

2020-12-09 18:28:27.290238+0900 309094_LocationManager[68978:11995386] Task <8B52D606-D4FD-4C06-8C33-F19D32528EB9>.<1> finished with error [-1022] Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection., NSErrorFailingURLStringKey=http://api.openweathermap.org/data/2.5/weat

こんな感じのエラーが出ていないでしょうか。
掲載されたコードでも、 ATS の設定を行えば一応動くようです。

投稿2020/12/09 09:30

TsukubaDepot

総合スコア5086

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

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

uma02

2020/12/09 10:07

ご回答ありがとうございます。 試してみたのですが、ATSの設定は既に行っているので原因はATSではないように思います。また、エラーは出ていないのですがログの内容を追加させていただいたのでもしよろしければ見ていただければと思います。
TsukubaDepot

2020/12/09 10:24

いや、きちんとエラーメッセージが出ているのが確認できます。 追記されたログには > The operation couldn’t be completed. (kCLErrorDomain error 0.) という具合に、 LocationManager 関連のエラーが出ているようです(このメッセージで検索されるとたくさんの事例が出てきます)。 ちなみに、Xcode12/iOS 14.2 の環境でご提示いただいたコードを試していますが、仮に GPS からの座標が得られない状態に設定しても、Cupertino の天候が出てきます。 どのようにすれば同じエラーがでるのか検討がつかないのですが、質問者さんの実行環境はどのようになっていますでしょうか。
uma02

2020/12/09 13:28

ご回答ありがとうございます。 こちらの環境もXcode12,iOS14ですが、実機テストはしておらずシュミレータを使っております。
TsukubaDepot

2020/12/10 00:59

ご提示されたコードの Alamofire は 4.x 系ですが、そのあたりの設定も Podfile などで行われているということでしょうか。ただ、これは上記コードの実行には直接関係ないのであくまで確認です。 少なくとも、ほぼお同じと思われる私の環境では、おそらく意図通りにうごきますので(Indicator も消えて、天気が表示される)ので、シミュレータの細かい設定などの問題かもしれません(私が想像できる範囲でいろいろ設定を変えてみましたが、上記のようなエラーは発生しませんでした)。 ちなみに、Alamofire をつかって API からデータを取得するだけというシンプルな構成にした場合でも、同じような問題は発生するのでしょうか。 何が原因か突き止めるためには、なるべくシンプルで本質的な構成に絞って問題を追求したほうがいいかと思います。
uma02

2020/12/10 06:17

ご回答ありがとうございます。また、色々と検討してくださり本当にありがとうございます。おっしゃっていただいたように一度シンプルな構成で試してみたいと思います。
TsukubaDepot

2020/12/10 06:40

それがいいかと思います。 現在の構成をおおまかにみると 1. CLLocationManager による現在位置の推定 2. AlamoFire を使った API へのアクセス 3. NVActivityIndicatorView を使った HUD の表示 となっていますので、それぞれ独立して検証できればいいのではないでしょうか。 ただ、エラーででている「The operation couldn’t be completed. (kCLErrorDomain error 0.) 」は、CLLocationManager 関連のエラーですので、現在のコードから 2. の部分を除いたコードを作ってみると現象がやりやすいのではないでしょうか。
uma02

2020/12/11 13:53

返信が遅くなり申し訳ありません。 実機で試したところ天気を取得することができました。 根本的なエラーの原因も探りますが、一旦これで解決にしたいと思います。 色々と教えてくださり本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問