LoginSignup
4
6

More than 3 years have passed since last update.

Alamofire + Combine を試す

Last updated at Posted at 2021-03-13

はじめに

最近、 iOS開発、SwiftUI の勉強をしているのですが、WebAPI の呼び出しをするため Alamofire を選定しました。
非同期処理では Alamofire + RxSwift などを使用するのが一般的のようですが、Alamofire 5.2.0 で Apple 製の非同期ライブラリ Combine がサポートされましたので、 Alamofire + Combine を試してみました。

ライブラリ等

Xcode : 12.4
Alamofire : 5.4.1

サンプルアプリ

サンプルアプリとして、Chatwork API トークンを TextField に入力させ、値が取得できたら name に名前をセットして表示する、ミニマムなアプリを作成しました。

WebAPI は Chatwork API/me を使用しています。

image.png

実装

LoginViewModel.swift
import Foundation
import Combine
import Alamofire

class LoginViewModel: ObservableObject {
    private var disposeBag = Set<AnyCancellable>()

    @Published var token = ""
    @Published var name = "name"

    func getMe() {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase

        AF.request("https://api.chatwork.com/v2/me", headers: ["X-ChatWorkToken": token])
            .publishDecodable(type: MeModel.self, decoder: decoder)
            .sink { data in
                guard let me = data.value else {
                    print("error")
                    return
                }
                print(me.name)
                print(me.accountId)
                self.name = me.name
            }.store(in: &disposeBag)
    }

}

.publishDecodable(type: MeModel.self, decoder: decoder)
が DataResponsePublisher を返却するため、Combine で扱うことができるようになります。

Chatwork API のレスポンスは、 key がスネークケースaccount_idですが、Swift ではキャメルケースaccountIdですので、
decoder.keyDecodingStrategy = .convertFromSnakeCase
で、変換するように指定しています。

Decodableを実装したデータモデルの定義

自分自身の情報を表すデータモデルは以下のように定義しました。

データの定義 MeModel.swift
MeModel.swift
import Foundation

struct MeModel: Decodable {
    var accountId: Int
    var roomId: Int
    var name: String
    var chatworkId: String
    var organizationId: Int
    var organizationName: String
    var department: String
    var title: String
    var url: String
    var introduction: String
    var mail: String
    var telOrganization: String
    var telExtension: String
    var telMobile: String
    var skype: String
    var facebook: String
    var twitter: String
    var avatarImageUrl: String
    var loginMail: String
}

参考までに、UIの定義はこんな感じです。

UIの定義 ContentView.swift
MeModel.swift
import SwiftUI

struct ContentView: View {
    @ObservedObject var viewModel = LoginViewModel()

    var body: some View {
        NavigationView {
            VStack(alignment: .center) {
                VStack(alignment: .leading) {
                    Text("Token")
                    TextField("token", text: $viewModel.token, onCommit: {
                    })
                        .keyboardType(.alphabet)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        .padding(.horizontal)

                    Text(viewModel.name)

                }
                    .padding(10)

                Divider()

                Button("Get") {
                    viewModel.getMe()
                }
                    .padding()
            }
                .overlay(RoundedRectangle(cornerRadius: 5).stroke())
                .padding(.horizontal, 50)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Moya は Combine に対応していない

ちなみに、Alamofire をより簡単に利用するための Moya というライブラリがありますが、14.0.0 では Combine にはまだ対応していません。
14.0.0 beta で一度導入されたものの、問題があってリリース前に消えたようです

4
6
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
4
6