2
2

More than 3 years have passed since last update.

【Swift】Closureを用いてAPIを扱う

Last updated at Posted at 2021-02-23

はじめに

今回は自分用メモです。
質問などはコメントのところで受け付けています!

今回したいこと

closureを用いてServerの通信が完了した後、成功したらUIを更新、失敗したらエラーアラートを出す処理を作る。
ネットワークエラーが発生した時のエラー内容をenumで書き出しておく。

enum NetworkError: Error, CustomStringConvertible {
    case unknown
    case invalidResponse
    case invalidURL
    var description: String {
        switch self {
        case .unknown: return "不明なエラーです"
        case .invalidResponse: return "不正なレスポンスです"
        case .invalidURL: return "不正なURLです"
        }
    }
}

次に、APIClientというクラスに通信処理を保持させておく。

class APIClient {
    func sendRequest(success: @escaping ([String: Any]) -> (), failure: @escaping (Error) -> ()) {
        //リクエストするURL。実際には存在するURLを用いる。
        guard let requestUrl = URL(string: "https://test") else {
            //もしrequestUrlがnilだったら、invalidURLエラーをfailure closureに渡し、処理を終える。
            failure(NetworkError.invalidURL)
            return
        }
        //URLRequest、URLSessionを作成している。
        let request = URLRequest(url: requestUrl)
        let session = URLSession.shared
        //Serverに対するリクエストを実行している。
        let task = session.dataTask(with: request) { (data, response, error) in
            if let error = error {
                //もしエラーだったら、errorをfailure closureに渡し、処理を終える。
                failure(error)
                return
            }
            guard let data = data else {
                //もしServerから何もデータが返ってこなかったら、unknownエラーをfailure closureに渡し、処理を終える。
                failure(NetworkError.unknown)
                return
            }
            //Serverから返って来たデータを辞書形式に変換する。
            guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
                //変換できない場合、invalidResponseエラーをfailure closureに渡し、処理を終える。
                failure(NetworkError.invalidResponse)
                return
            }
            //jsonをsuccess closureに渡す。
            success(json)
        }
        task.resume()
    }
}

呼び出したい場所で以下のように記述すればServerに対してリクエストが成功した後、もしくは失敗した後特定の処理を記述できる。

let api = APIClient()
api.sendRequest(success: { (json) in
    //success closureが来た時の処理(引数はjson)
    //UIの更新
}) { (error) in
    //failure closureが来た時の処理(引数はerror)
    //エラーアラート
}

最後に

今回のclosureはコールバック関数みたいな使われ方をしてますね。

2
2
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
2
2