概要
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の実装
必要な箇所だけ抜き出します。
通信をし、レスポンスを受け取ったタイミングでリポジトリの一覧を更新します。
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からの通知を受け取り次第、テーブルを更新します。
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に慣れてくるとクラス間の通知にすごく重宝します。
参考記事