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

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

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

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

Q&A

解決済

1回答

911閲覧

MoyaでAPIへのアクセスを行たい

hodoru3sei

総合スコア284

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/06/19 09:32

Moyaでlivedoor天気予報のAPIにアクセスしてjsonを取得したいと考えています。
qiitaの記事ブログ記事を参考に実装してみたのですが、アクセスに失敗してしまいます。

コード

Moyaのenum宣言部分では東京と大阪の2ヶ所を設定しています。

Swift

1import Moya 2 3enum TenkiAPI { 4 case tokyo 5 case osaka 6} 7extension TenkiAPI: TargetType { 8 9 10 var baseURL:URL { 11 return URL(string:"http://weather.livedoor.com/forecast/webservice/json/v1")! 12 } 13 var path: String { 14 switch self { 15 case .tokyo: return "?city=130010" 16 case .osaka: return "?city=270000" 17 } 18 } 19 20 var method: Moya.Method { 21 switch self { 22 case .tokyo, .osaka: 23 return .get 24 } 25 } 26 27 //テストの際に使うメソッド 28 var sampleData: Data { 29 return Data() 30 } 31 32 var task: Task { 33 switch self { 34 case .osaka, .tokyo: 35 return .requestPlain 36 } 37 } 38 39 var headers: [String : String]? { 40 return nil 41 } 42 43}

viewDidLoadでAPIへのアクセスを試みたのですが失敗して.failureに飛んでしまいます。

Swift

1 override func viewDidLoad() { 2 super.viewDidLoad() 3 let provider = MoyaProvider<TenkiAPI>() 4 provider.request(.tokyo) { result in 5 switch result { 6 case let .success(moyaResponse): 7 do { 8 try moyaResponse.filterSuccessfulStatusCodes() 9 let data = try moyaResponse.mapJSON() 10 // do something with the data 11 } 12 catch { 13 print("json parse失敗") 14 } 15 case let .failure(error): 16 print("アクセスに失敗しました:(error)") 17 break 18 } 19 20 } 21 }

アクセスの方法が間違っているのでしょうか?

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

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

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

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

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

hayabusabusash

2019/06/26 02:22

エラーをプリントしているみたいなので出力されたエラーを見せていただけないでしょうか? Moyaのenum内のpathにクエリ文字列が入っているのでパラメータを使うようなAPIだと思いますが、 その場合parametersとparameterEncodingを使ったほうがいいと思います。 憶測で申し訳ありませんがpath内の?が別の文字に変換されてしまっているのが原因なんじゃないかなと思います。
hodoru3sei

2019/06/26 08:49

エラー ログは以下の様なものが出力されています ``` 2019-06-26 17:44:38.293770+0900 MoyaTest[5093:446654] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file. 2019-06-26 17:44:38.293818+0900 MoyaTest[5093:446654] Cannot start load of Task <0DB862E5-A5AB-4186-8213-CCC7AE52F05C>.<1> since it does not conform to ATS policy 2019-06-26 17:44:38.293901+0900 MoyaTest[5093:446652] Task <0DB862E5-A5AB-4186-8213-CCC7AE52F05C>.<1> finished with error - code: -1022 アクセスに失敗しました:underlying(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={NSUnderlyingError=0x1d4649ba0 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}, NSErrorFailingURLStringKey=http://weather.livedoor.com/forecast/webservice/json/v1/%3Fcity=130010, NSErrorFailingURLKey=http://weather.livedoor.com/forecast/webservice/json/v1/%3Fcity=130010, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.}, nil ``` ?はそのままだと変換されてしまうのでしょうか?API通信をするのがほぼ初めてであまり理解していませんでした。 サンプルに以下の様な記載があったので東京と大阪それぞれの番号の前に?city=をつけていました http://weather.livedoor.com/forecast/webservice/json/v1?city=400040
guest

回答1

0

ベストアンサー

エラーの記載ありがとうございます!

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

まずAPIのベースのURLがhttpなので、
http通信を許可するようにinfo.plistに編集が必要です。(こちらを参考にしてください)

NSErrorFailingURLStringKey=http://weather.livedoor.com/forecast/webservice/json/v1/%3Fcity=130010,

パスに指定していた?が%3Fになっていたのも原因のようです。
なので以下のようにしてみました。

Swift

1import Moya 2 3enum LivedoorWeatherAPI { 4 case tokyo 5 case osaka 6} 7 8extension LivedoorWeatherAPI: TargetType { 9 10 var baseURL: URL { 11 guard let url = URL(string: "http://weather.livedoor.com/forecast/webservice/json/v1") else { 12 fatalError("base URL error") 13 } 14 return url 15 } 16 17 var path: String { 18 switch self { 19 case .tokyo: 20 return "" 21 case .osaka: 22 return "" 23 } 24 } 25 26 var method: Method { 27 switch self { 28 case .tokyo, .osaka: 29 return .get 30 } 31 } 32 33 var sampleData: Data { 34 return Data() 35 } 36 37 // 新しく追加 パラメータ名がキーになります 38 var parameters: [String: Any] { 39 switch self { 40 case .tokyo: 41 let parameter = [ 42 "city": "130010" 43 ] as [String: Any] 44 return parameter 45 case .osaka: 46 let parameter = [ 47 "city": "270000" 48 ] as [String: Any] 49 return parameter 50 } 51 } 52 53 // 新しく追加 URLにクエリ文字列として組み込む 54 var parameterEncoding: ParameterEncoding { 55 switch self { 56 case .tokyo, .osaka: 57 return Moya.URLEncoding.queryString 58 } 59 } 60 61 // 新しく追加 上で定義した parameters と parameterEncoding を使うに指定 62 var task: Task { 63 switch self { 64 case .tokyo, .osaka: 65 return .requestParameters(parameters: parameters, encoding: parameterEncoding) 66 } 67 } 68 69 var headers: [String : String]? { 70 return ["Content-type": "application/json"] 71 } 72} 73

この状態で同じように通信してみるとエラーではなく、なんらかのレスポンスが返ってきたので、
一応通信は成功したんじゃないかな?と思います。

Swift

1class ViewController: UIViewController { 2 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 6 let provider = MoyaProvider<LivedoorWeatherAPI>() 7 provider.request(.tokyo) { result in 8 switch result { 9 case let .success(moyaResponse): 10 do { 11 try moyaResponse.filterSuccessfulStatusCodes() 12 let data = try moyaResponse.mapJSON() 13 print(data) 14 // do something with the data 15 } 16 catch { 17 print("json parse失敗") 18 } 19 case let .failure(error): 20 print("アクセスに失敗しました:(error)") 21 break 22 } 23 } 24 } 25 26 27}

投稿2019/06/26 09:35

hayabusabusash

総合スコア767

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

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

hodoru3sei

2019/06/27 01:19

丁寧にありがとうございます! すごく参考になりました!!!
hayabusabusash

2019/06/27 03:48 編集

よかったです! せっかくなので今日の天気を表示するところまでサンプルを作ってみました。 雑な部分もありますが、よければご確認ください。 ( https://github.com/hayabusabusa/TeratailMoyaTest ) 追記: URLが変だったので修正しました。
hodoru3sei

2019/06/27 03:37

ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問