LoginSignup
5
3

More than 1 year has passed since last update.

【SwiftUI】AlamofireをCombineで使ってみた

Posted at

はじめに

以前はCombineでURLSessionを使って通信をしてみました。
今回はCombineでAlamofireを使って通信してみます。

サンプルアプリ

Simulator Screen Recording - iPhone 14 Pro - 2022-11-21 at 20.36.34.gif

実装

View

ContentView
import SwiftUI

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    var body: some View {
        List(viewModel.repositories.items) { item in
            Label {
                Text(item.name)
            } icon: {
                avatar(item: item)
            }
        }
        .listStyle(.grouped)
    }
    func avatar(item: Item) -> some View {
        AsyncImage(url: URL(string: item.owner.avatarURL), transaction: .init(animation: .default)) { result in
            switch result {
            case .success(let success):
                success
                    .resizable()
                    .scaledToFit()
                    .clipShape(Circle())
            default:
                ProgressView()
            }
        }
    }
}

ViewModel

ViewModel
import Alamofire
import Combine
import Foundation

final class ViewModel: ObservableObject {
    @Published var repositories: SearchRepositories = .init(items: [])

    private let url = "https://api.github.com/search/repositories?q=swift"

    private var cancellable = Set<AnyCancellable>()

    init() {
        fetchSearchRepositories()
    }

    private func fetchSearchRepositories() {
        AF.request(url, method: .get).publishDecodable(type: SearchRepositories.self)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] response in
                guard let self else { return }
                switch response.result {
                case .success(let response):
                    self.repositories = response
                case .failure:
                    self.repositories = .init(items: [])
                }
            }
            .store(in: &cancellable)
    }
}

Model

SearchRepositories
import Foundation

// MARK: - SearchRepositories
struct SearchRepositories: Codable {
    var items: [Item]

    enum CodingKeys: String, CodingKey {
        case items
    }
}

// MARK: - Item
struct Item: Codable, Identifiable {
    let id = UUID()
    let name: String
    let owner: Owner
    let htmlURL: String
    let itemDescription: String?
    let languagesURL: String
    let stargazersCount: Int
    let language: String?
    let forksCount: Int
    let openIssuesCount: Int

    enum CodingKeys: String, CodingKey {
        case name
        case owner
        case htmlURL = "html_url"
        case itemDescription = "description"
        case languagesURL = "languages_url"
        case stargazersCount = "stargazers_count"
        case language
        case forksCount = "forks_count"
        case openIssuesCount = "open_issues_count"
    }
}

// MARK: - Owner
struct Owner: Codable {
    let login: String
    let avatarURL: String
    let url: String
    let htmlURL: String

    enum CodingKeys: String, CodingKey {
        case login
        case avatarURL = "avatar_url"
        case url
        case htmlURL = "html_url"
    }
}

おわり

Combineを使うとコードがスッキリするので結構好きです

5
3
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
5
3