アジェンダ

  • はじめに
  • Combineの基本概念
  • Combineを使う理由
  • Combineを使うサンプル

はじめに

Combineは、Appleが公式で提供する非同期イベントを処理するフレームワークです。Xcode 11から利用可能になった新しいフレームワークで導入可能なターゲットバージョンはSwiftUI同様に13.0以降になります。

Combineの基本概念

Combineは「Publisher」「Subscriber」「Operator」の3要素からなり、値を提供するPublisherと、その値を購読するSubscriberの2者間におけるデータの受け渡しが、Combineの主な役割となります。

1. Publisher: Publisherは値を生成し、それらをSubscriberに送信します。
 以下、実装例です。

let publisher = [1, 2, 3, 4, 5].publisher

2. Subscriber: SubscriberはPublisherから値を受け取り、それらの値をどのように処理するかを決定します。
 以下、実装例です。

let publisher = [1, 2, 3, 4, 5].publisher
let subscriber = publisher.sink { value in
  print("Received value: (value)")
}

3. Operator: OperatorはPublisherの間に挿入され、Publisherから送信される値を変換することができます( map、filter、reduce、scan など )。
 以下、実装例です。

let publisher = [1, 2, 3, 4, 5].publisher

 // Filter
let filterArray = publisher.filter { $0 % 2 == 0 }  // 結果:[2, 4]

 // Map
let mapArray = publisher.map { $0 * 2 }  // 結果:[2, 4, 6, 7, 10]

 // Reduce
let totalSum = publisher.reduce(0, +)    // 結果:totalSum = 15

 // Scan
let scanArray = publisher.flatMap { array in
                    Publishers.Sequence(sequence: array)
                              .scan(0, +)
                              .collect()
                }                          // 結果:[1, 3, 6, 10, 15]
// Merge
let publisher2 = [6, 7, 8, 9].publisher
let mergeArray = publisher.merge(with, publisher2)  // 結果:[1, 2, 3, 4, 5, 6, 7, 8, 9]

Combineを使う理由

  1. Combineを利用することで、イベントごとに処理を一元化でき、クロージャ、コールバック、デリゲートなどの複雑で追いにくいものを排除することができます。その結果、コードの読み取りや保守が容易になるメリットに繋がります。
  2. SwiftUIを使ってアプリを作る場合は、ObservableObject Protocolや@PublishedなどのProperty wrapperなど、Combineを知らない人でも機能の一部を知らないうちに使用していたりしています。
  3. Combineを用いた非同期処理の実装: Combineを使って非同期のタスクを実装する方法を学びます。これには、APIからのデータの取得やユーザーインターフェースの更新などが含まれます。
  4. エラーハンドリング: Combineを使ってエラーをどのように扱うかを学びます。これは特に非同期のタスクで重要です。

Combineを使うサンプル

必須ライブラリのインポート

import SwiftUI
import Combine

ViewModelの設定

ContentViewModelクラスはObservableObjectプロトコルに準拠し、@Published属性を使用してinputTextプロパティを公開します。このプロパティの変更はビューに通知されます。

class ContentViewModel: ObservableObject {
    @Published var inputText: String = ""
}

Viewの設定

ContentView構造体はViewプロトコルに準拠し、@StateObject属性を使ってViewModelを保持します。TextFieldはユーザーの入力を受け取り、$viewModel.inputTextにバインドされます。
TextビューはViewModelのinputTextプロパティをリアルタイムで表示します。

// SwiftUI View
struct ContentView: View {
    @StateObject private var viewModel = ContentViewModel()

    var body: some View {
        VStack {
            TextField("Enter text", text: $viewModel.inputText)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Text(viewModel.inputText)
                .padding()
        }
        .padding()
    }
}

実行結果

このコードを実行すると、ユーザーがテキストフィールドに文字を入力するたびに、その内容がリアルタイムで下のテキストビューに表示されます。Combineフレームワークを使って、ViewModelのプロパティの変更がSwiftUIビューにリアクティブに反映される仕組みを実現しています。

最後に

簡単なアプリを使って、SwiftUIとCombineの単純な扱い方を復習してみました。
SwiftUIとCombineを活用することで、クロージャーやデリゲートなどの複雑な非同期処理を簡素化し、コードの可読性や保守性を向上させることができます。
今回だけでは説明しきれないほど、SwiftUIとCombineには他にも沢山の機能があります。
今回記事にして復習してみると、新しく追加されている機能も多々あるようなので、引き続き調べていきたいと思います。



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる