はじめに
以前はCombineでURLSessionを使って通信をしてみました。
今回はCombineでAlamofireを使って通信してみます。
サンプルアプリ
実装
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を使うとコードがスッキリするので結構好きです