概要
Combine
とUIKit
を組み合わせて使う時のメモです。
SwiftUI
とCombine
を組み合わせた実装経験はあったのですが、UIKit
と一緒に使ったことがありませんでした。
今回、UIKit
とCombine
を一緒に使ってデモを作成してみます。
環境
macOS Monterey 12.6
Xcode 14.1
主な使用技術
UIKit
Combine
完成形
想定しているのは、GitHubのリポジトリを検索・表示するアプリです。
ざっくりとした流れ
UITableView
の組み方や外部との通信の箇所は割愛します。
最後に全体のソースコードを載せるので、是非確認してみください。
ディレクトリ構造
UITableView
を表示するHomeViewController
とそれに対応するHomeViewModel
があります。
HomeViewController
にGithubのリポジトリ一覧を保持し、HomeViewController
でそれを表示する感じです。
ViewModel
の実装
必要な箇所だけ抜き出します。
通信をし、レスポンスを受け取ったタイミングでリポジトリの一覧を更新します。
HomeViewModel.swift
import Combine
class HomeViewModel {
...
private(set) var githubRepositoriesSubject: CurrentValueSubject<[GitHubRepository], Never> = .init([])
...
private func updateGithubRepositores() {
...
let response = try await apiService.searchGithubRepository(query: query)
let repositories = response.items
githubRepositoriesSubject.send(repositories)
...
}
}
ViewController
の実装
ViewModel
からの通知を受け取り次第、テーブルを更新します。
HomeViewController.swift
import Combine
class HomeViewController: UIViewController {
...
private let viewModel: HomeViewModel = .init()
private var cancellables: Set<AnyCancellable> = []
...
init() {
subscribeGithubRepositores()
}
deinit {
cancellables.forEach { $0.cancel() }
}
private func subscribeGithubRepositores() {
viewModel.githubRepositoresSubject
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
guard let self = self else { return }
self.tableView.reloadData()
}
.store(in: &cancellables)
}
}
まとめ
全てのソースコードはこちらにまとめてあります。
Combine
に慣れてくるとクラス間の通知にすごく重宝します。
参考記事