【Swift】Alamofireの導入と使い方!HTTP通信とAPI

この記事からわかること
- SwiftのAlamofireの導入方法
- HTTP通信のやり方
- APIを操作するには?
- AFやSessionクラスの使い方
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- Alamofire:5.10.2
- macOS:Sonoma 14.6.1
Alamofireとは?

AlamofireとはSwiftで使用されるHTTPネットワーキングライブラリです。ネットワーク通信に関わるリクエスト/レスポンス処理だけでなく、ファイルのアップロード、非同期処理、JSONパラメータのエンコーディング、認証機能などさまざまな特徴を持っています。
アプリでの使い所としてはAPI通信(Qiitaの記事やGitHubのリポジトリの取得)などによく活用されています。
ちなみにAlamofireでアラモファイアと読み、言葉の由来はテキサス州の公式州花になっている花の名前のようです。
Alamo Fire Lupinus texensis (マメ科)
APIとは?
そもそもAPIとは「Application Programming Interface」の略称でアプリやプログラム、Webサービス同士を繋ぐインターフェースのことを指します。
サービス同士を繋ぐ形で提供されているものはAPIと呼ばれますが今回はWeb上からJSON形式でデータを受け取り、アプリ内で参照するために使用するようなAPIを使用していきます。
Xcodeでの導入
Alamofireは普通のライブラリ同様にCocoaPodsやSwift Package Managerなどのツールを利用してXcodeに導入することが可能です。
CocoaPods
pod 'Alamofire'
Swift Package Manager
https://github.com/Alamofire/Alamofire.git

Xcodeにライブラリを導入できたら使用するファイルの上部でimport
しておきます。
import Alamofire
APIの取得方法
では実際にHTTPリクエストを送信し、APIからデータを取得してみます。今回は当サイト「Webエンジニア学習部屋」の記事を全て取得するAPIにアクセスしてみたいと思います。
上記のURLを叩いて取得できるのはJSON形式の文字の羅列です。これを任意の形に変換することでアプリ内から操作しやすいようにしていけばOKです。今回の変換部分はAlamofireとは関係ないので通信部分に焦点を当てて実装してみます。
import SwiftUI
import Alamofire
struct AlamofireView: View {
func getArticles(){
AF.request("https://appdev-room.com/api/article").response { response in
do {
let articles = try JSONSerialization.jsonObject(with: response.data!, options: []) as? Array<Any>
print(articles)
} catch {
print(error.localizedDescription)
}
}
}
var body: some View {
Button {
getArticles()
} label: {
Text("get")
}
}
}
AF(Session.default)
AF
の定義を見てみると実態はdefault
プロパティで定義されたシングルトンのSession
クラスになっています。
public let AF = Session.default
open class Session {
/// Shared singleton instance used by all `AF.request` APIs. Cannot be modified.
public static let `default` = Session()
}
requestメソッド
リクエストを送信するのはrequest
メソッドです。引数にURLやHTTPメソッド、パラメータを渡すことで任意のリクエストを送信することが可能になっています。
open class Session {
open func request(_ convertible: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
interceptor: RequestInterceptor? = nil,
requestModifier: RequestModifier? = nil) -> DataRequest {
let convertible = RequestConvertible(url: convertible,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers,
requestModifier: requestModifier)
return request(convertible, interceptor: interceptor)
}
}
HTTPメソッドを切り替える
requestメソッドの引数にはHTTPMethod型でGETやPOSTなどのHTTPメソッドを指定することができます。
// GET
AF.request(url, method: .get)
// POST
AF.request(url, method: .post)
パラメータ(データ)を渡す
APIでよくあるのがリクエストにJSONデータなどを渡して情報を登録したりする方法だと思います。AlamofireではParameters型([String: Any]型のエイリアス)のキーバリューペアでデータを渡すことが可能です。
GET
を指定してパラメータを渡すとクエリで?key1=value1&key2=value2
のように指定した意味になるようです。
let parameters: [String: Any] = ["key1": "value1", "key2": "value2"]
AF.request(url, method: .get, parameters: parameters).response() { response in }
POST
を指定してパラメータを渡すとHTTPBodyにJSONエンコードして含めるように指定した意味になるようです。
let parameters: [String: Any] = ["key1": "value1", "key2": "value2"]
AF.request(url, method: .post, parameters: parameters)
Headerを追加する
HTTP通信のHeaderを追加したい場合はHTTPHeaders
型で渡すことが可能です。例えば認証用のBearerトークンを渡したい場合は以下のようになります。
let headers: HTTPHeaders = ["Authorization": "Bearer your_token"]
AF.request(url, method: .get, parameters: parameters, headers: headers).response() { response in }
responseメソッド
HTTP通信の結果を受け取るにはresponse
メソッドを使用します。クロージャーの引数からAFDataResponse<Data?>
型でレスポンスを取得することが可能です。
AF.request(url).response { response in
do {
let articles = try JSONSerialization.jsonObject(with: response.data!, options: []) as? Array<Any>
print(articles)
} catch {
print(error.localizedDescription)
}
}
また引数queue
では実行スレッドを明示的に指定することも可能です。
.response(queue: DispatchQueue.global(qos: .background)) { response in }
画像ファイルなどを送信する
データではなく画像ファイルなどを送信したい場合はuploadメソッドを使用します。引数multipartFormData
のクロージャからMultipartFormData
型を取得しそこにappend
する形で画像ファイルを指定します。
append
する際にはwithName
にサーバー側で取得するキー名をmimeType
に形式を指定し、HTTPメソッドはPUT
を指定します。
AF.upload(
multipartFormData: { multipartFormData in
// 画像を少し圧縮して追加
if let imageData = image.jpegData(compressionQuality: 0.8) {
multipartFormData.append(
imageData,
withName: "file", // サーバー側で取得するキー
fileName: "fineName.jpg",
mimeType: "image/jpeg"
)
}
},
to: url,
method: .put
).response() { response in }
例えばバックエンド側をLaravelで実装している場合は$request->file
から画像を取得することができます。
if ($request->file !== null) {
// 画像を保存するなど
}
Laravelで画像を保存するなら「Intervention Image」が便利です。
画像ファイルと一緒にデータも送信する
画像ファイルと一緒にパラメータにデータを渡したい場合はいくつか注意点があります。multipartFormData
に対象のデータをData
型にキャストして追加してみたのですがバックエンド側(Laravelでは$request)からは取得することができませんでした。
解決方法
- HTTPメソッドはPOSTを指定する
- 「Content-Type」に「multipart/form-data」を指定する
- 「X-HTTP-Method-Override」にPUTを指定する
色々試した結果$request
に格納されるようにするためにはPOST
通信にする必要があったようです。そして画像も一緒に送るためにはX-HTTP-Method-Override
でPUT
を指定することで画像とデータを一緒に送信することができるようになりました。
let headers: HTTPHeaders = [
"Content-Type": "multipart/form-data",
"X-HTTP-Method-Override": "PUT"
]
AF.upload(
multipartFormData: { multipartFormData in
parameters.forEach { key, value in
let stringValue: String?
// 送信対象のパラメータを構築
switch value {
case let string as String:
stringValue = string
case let int as Int:
stringValue = "\(int)"
case let bool as Bool:
stringValue = bool ? "true" : "false"
default:
stringValue = nil
}
if let data = stringValue?.data(using: String.Encoding.utf8) {
multipartFormData.append(data, withName: key)
}
}
if let imageData = image.jpegData(compressionQuality: 0.8) {
multipartFormData.append(
imageData,
withName: "file", // サーバー側で取得するキー
fileName: "fineName.jpg",
mimeType: "image/jpeg"
)
}
},
to: url,
method: .pos,
headers: headers
).response() { response in }
JSON形式のデコーティング
取得したJSON形式のデータは必要に応じてSwiftで扱いやすいデータ型に変換します。先ほどはJSONSerialization
クラスを使用して配列型に変換することで出力していました。
let articles = try JSONSerialization.jsonObject(with: response.data!, options: []) as? Array<Any>
構造体(クラス)に変換する
辞書型ではなく、構造体(orクラス)に変換するにはJSONDecoderクラス
を利用します。詳細は以下の記事を参考にしてください。
構造体に変換するポイント
- モデルの作成
- デコード
変換対象となるモデル構造体(orクラス)を先に定義しておきます。
モデル構造体の作成
struct Article: Decodable{
let id:Int
let title:String
}
JSONDecoderクラスによる変換
AF.request("https://appdev-room.com/api/article")
.responseData { response in
do {
let decoder: JSONDecoder = JSONDecoder()
let articles: [Article] = try decoder.decode([Article].self, from: response.data!)
print(articles)
} catch {
print(error.localizedDescription)
}
}
SwiftオリジナルのHTTP通信クラス
ライブラリではなくSwiftに既に組み込まれているURLSessionクラスでもHTTP通信が可能になっています。
Alamofire
を使用した処理もURLSessionクラスを用いて以下のように記述することも可能です。
func getArticleAPI() {
let urlString = "https://appdev-room.com/api/article"
// 有効なURLかをチェック
if validationUrl(urlString: urlString) == false {
return
}
guard let url = URL(string: urlString) else {
return
}
// リクエストを構築
let request = URLRequest(url: url)
// URLにアクセスしてレスポンスを取得する
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
do {
let articles = try JSONSerialization.jsonObject(with: data, options: []) as? Array<Any>
print(articles)
} catch {
print(error.localizedDescription)
}
}
}.resume()
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。