LoginSignup
0
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-11-21

はじめに

HTTP通信はいつもAlamofireを使用していて、URLSessionを使ったことがなかったので使ってみました。

サンプルアプリ

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

実装

View

ContentView.swift
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.swift
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() {
        URLSession.shared.dataTaskPublisher(for: URL(string: url)!)
            .tryMap { data, _ in return data }
            .decode(type: SearchRepositories.self, decoder: JSONDecoder())
            .receive(on: DispatchQueue.main)
            .sink { complete in
                print(complete)
            } receiveValue: { [weak self] response in
                guard let self else { return }
                self.repositories = response
            }
            .store(in: &cancellable)
    }
}

Model

SearchRepositories.swift
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"
    }
}

おわり

普通にURLSessionを使うとごちゃごちゃした感じになりますが、Combineで使うとスッキリしてますね。
これならAlamofireじゃなくて、URLSessionを採用してもいいかなと思いました。

0
1
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
0
1