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

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

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

RxSwiftは、Reactive ExtensionsのSwift向けの実装です。iOS開発に用いられ、リアクティブプログラミングを可能にします。

Q&A

解決済

1回答

2364閲覧

SwiftにてURLSessionの結果がエラーの場合、例外をスローするなどして呼び出し元で処理を行いたい。

koikuti

総合スコア50

RxSwift

RxSwiftは、Reactive ExtensionsのSwift向けの実装です。iOS開発に用いられ、リアクティブプログラミングを可能にします。

0グッド

0クリップ

投稿2022/06/29 04:02

前提

SwiftでiOSアプリを作成しています。
この中で、URLSession を使用してAPIアクセスしているのですが、
エラーハンドリングについて質問になります。

Swift, iOSについて初心者で、調べ調べなんとかかんとかやっており、
Swiftではそんなやり方しない、というようなお作法などにも疎いため、
的はずれなことをやろうとしているかもしれません。

実現したいこと

APIアクセスの結果が、エラーあるいはレスポンスのステータスコードが成功以外の時、
例外をスローして外側でエラー時の処理をしたい。

発生している問題・エラーメッセージ

該当のソースコードに埋め込んだコメントここを throw にしたいの部分をthrowにすると、
Invalid conversion from throwing function of type '(Data?, URLResponse?, Error?) throws -> Void' to non-throwing function type '(Data?, URLResponse?, Error?) -> Void'
のエラーになる。

URLSession.shared.dataTaskcompletionHandler が例外スローできるものではないので当然ではあるのですが...。

他の言語などで、APIリクエストする場合、HTTPステータスコードに合わせて、適当な例外をスローして、
呼び出し元で処理するということはあると思っておりまして。

該当のソースコード

swift

1func postApi() -> Void { 2 guard let url = URL("hogegApiUrl") else {return} 3 4 var request = URLRequest(url) 5 request.httpMethod = "POST" 6 request.setValue("Application/json", "Content-Type") 7 8 URLSession.shared.dataTask(request) {(data, response, error) in 9 if let error = error { 10 print("APIアクセス時にエラーが発生しました。: error={\(error)}") 11 return // ここを throw error などにして、関数の呼び出し元で処理したい。 12 } 13 14 if let response = response as? HTTPURLResponse { 15 if !(200...299).contains(response.statusCode) { 16 print("レスポンスのステータスコードが成功以外でした。: response={\(response)}") 17 return // ここも throw NSError() などにして、関数の呼び出し元で処理したい。 18 } 19 20 // リクエスト成功時の処理 2122 23 } 24 }.resume() 25 26}

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

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

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

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

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

koikuti

2022/06/30 06:54

ご助言ありがとうございます。 リンク先の内容をあまり理解できず、別の方法で自己解決となりました。
guest

回答1

0

自己解決

例外をスローするのではなく、呼び出し元から処理用のハンドラーを受け取る形で、
呼び出し元で行いたい処理を実行する形にしました。

swift

1func postApi(errorHandler: ((_ err: Error) -> Void)? , responseHandler: ((_ response: HTTPURLResponse) -> Void)? ) -> Void { 2 // 引数として、エラー、レスポンスに対するコールバックハンドラを受け取るようにしました。 3 4 guard let url = URL("hogegApiUrl") else {return} 5 6 var request = URLRequest(url) 7 request.httpMethod = "POST" 8 request.setValue("Application/json", "Content-Type") 9 10 URLSession.shared.dataTask(request) {(data, response, error) in 11 if let error = error { 12 print("APIアクセス時にエラーが発生しました。: error={\(error)}") 13 errorHandler(error) 14 return 15 } 16 17 if let response = response as? HTTPURLResponse { 18 if !(200...299).contains(response.statusCode) { 19 print("レスポンスのステータスコードが成功以外でした。: response={\(response)}") 20 responseHandler(response) 21 return 22 } 23 24 // リクエスト成功時の処理 2526 27 } 28 }.resume() 29 30}

swift

1// 呼び出し元 2 3let hoge = Hoge() 4 5hoge.postApi(errorHandler: errorHandler, responseHandler: responseHandler) 6 7private func errorHandler(err: Error) -> Void { 8 // エラー時にやりたい処理 9 print("とりあえずログで出しておく。error={\(err)}") 10} 11 12private func responseHandler(res: HTTPURLResponse) -> Void { 13 // レスポンスが成功以外の時にやりたい処理 14 print("とりあえずログで出しておく。response={\(res)}") 15}

投稿2022/06/30 07:10

編集2022/06/30 07:12
koikuti

総合スコア50

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問