yujiro's blog

エンジニアリング全般の事書きます

【Swift】Alamofire を使って色んなリクエストを投げてみる

iOSでHTTPリクエストをする際によく使われるAlamofire の使い方を紹介します。

Alamofire は HTTPリクエストをするのにrequest, download, upload メソッドが用意されています。

今回はこれらの基本的な使い方について紹介しようと思います。

事前に用意したものとしては、web サーバーを適当に立てています。

今回はRailslocalhost:3000 でアクセスできるようにしておきました。

あと、xcode 上でhttps でなくても通信できようにInfo.plist に

NSAppTransportSecurity

をDictionaryで追加し、その下に

NSAllowsArbitraryLoads 

を YES で設定しています。

スクリーンショット 2018-07-01 16.42.14.png (105.6 kB)

ちなみに Alamofire のバージョンは4.7.2 です。

request メソッド

request はその名前の通りシンプルにHTTPリクエストをするのに使用されます。

http メソッドについては以下のようにenum が定義されており、まぁ全部網羅されてます。

public enum HTTPMethod: String {
    case options = "OPTIONS"
    case get     = "GET"
    case head    = "HEAD"
    case post    = "POST"
    case put     = "PUT"
    case patch   = "PATCH"
    case delete  = "DELETE"
    case trace   = "TRACE"
    case connect = "CONNECT"
}

get リクエストを投げてみます。

let urlString: String = "http://localhost:3000"

let parameters: Parameters = ["foo": "bar"]

Alamofire.request(urlString, method: .get, parameters: parameters)
    .downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
        print("Progress: \(progress.fractionCompleted)")
    }
    .validate { request, response, data in
        // Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
        return .success
    }
    .responseJSON { response in
        debugPrint(response)
        switch response.result {
        case .success:
            print("Success!")
        case .failure:
            print("Failure!")
        }
}

上記の場合、シンプルにhttp://localhost:3000?foo=bar というURLのリクエストが送信されます。

responseJSON としているので、レスポンスボディをjson パースできないとresponseSerializationFailed というエラーになります。

また、公式のgithubguide ページで紹介されているコードだと

Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default)

となっていますが、encoding: JSONEncoding.default は、JSON形式でパラメータを送るためにリクエストヘッダーにContentType:application/json と付与する方法でここでは不要なのと、実際につけて送信すると、なぜかリクエストがTimeout になってしまいました。

.post では正常にリクエストされます。

timeout になったあとに、response をdebug してみるとどんなリクエストを送ったかわかるのですが、それと同じように curl コマンドなどでリクエストをしてみると正常に通るので、謎です。

調べたら、issue が立ってました。 https://github.com/Alamofire/Alamofire/issues/1819

まぁ、シンプルなパラメータ構造ならjson encoding は不要なので一旦飛ばします。

validate

上記コードのvalidate というメソッドですが、これはレスポンスを受け取ったあとに、ヘッダの情報をみてエラーと判断したい場合に有効です。

例えば、API通信をした際に、レスポンスヘッダのContent Type がキチンとapplication/json になっているかを確認し、なっていなかったら失敗としたい場合は

Alamofire.request(urlString, method: .get, parameters: parameters)
    .validate(contentType: ["application/json"])
    .responseJSON { response in
...

とすればOKです。

download メソッド

download はHTTPリクエストした結果のレスポンスをローカルに保存するために使用されます。その用途としては例えば、web上にあるpdf をダウンロードしてビューアーで表示、みたいな感じです。

ここでは、それを実装してみます。

下記を参考にしました。

Swift3とAlamofireでPDFファイルをダウンロードしてReaderで表示する

Reader のライブラリは vfrReader というやつの2.8.6 を使っています。

https://github.com/vfr/Reader

class ViewController: UIViewController, ReaderViewControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        
        let urlString: String = "http://www.pdf995.com/samples/pdf.pdf"
        let destination = DownloadRequest.suggestedDownloadDestination()
        Alamofire.download(urlString, to: destination).validate().responseData { response in
            debugPrint(response)
            guard
                let pdfPath = response.destinationURL?.path,
                let document = ReaderDocument(filePath: pdfPath, password: nil),
                let readerVC = ReaderViewController(readerDocument: document) else {
                return
            }
            readerVC.delegate = self
            readerVC.modalPresentationStyle = .fullScreen
            self.present(readerVC, animated: false, completion: nil)
        }
    }
....

スクリーンショット 2018-07-01 17.05.55.png (85.1 kB)

ポイントは download を使うと

 response.destinationURL

というプロパティがセットされることです。

これがコンテンツをダウンロードしたローカルのパスになっています。

upload

Comming soon

参考

Swift3とAlamofireでPDFファイルをダウンロードしてReaderで表示する