🔗

Subject からはじめる Combine

2020/10/12に公開

はじめてCombineを学ぶ人向けに「Combineをはじめよう」という本を書きました。この記事では、その本についての補足のような内容(あるいは裏話のような内容)を書きます。

Combineをはじめる敷居を下げる

CombineはSwiftでリアクティブプログラミングを行うためのフレームワークです。各種の非同期イベントのハンドリングに使うことができます。類似のものとしてRxSwift、ReactiveSwiftなどがあります。Combineは標準フレームワークのひとつとして加わったため、今後、採用事例が増えると思われます。

リアクティブプログラミングには、敷居が高い、学習コストが高い、というイメージがあります。しかし、実はそんなに難しいものではないのです。そこで、上述の本ではCombineをはじめる敷居を下げたいと考えました。

最初のほうに、学ぶ方針として以下のように書きました。

プログラマであれば、言葉であれこれ説明する前に、実際にコードを書いて動かしてみるのが理解が早いだろう

この考えにもとづいて、Xcode Playgroundですぐに動かせるコードを用意しました。すぐ動かせるようにすることで敷居を下げる狙いです。

import Combine

let subject = PassthroughSubject<String, Never>()

subject
    .sink { value in
        print("Received value:", value)
    }

subject.send("あ")
subject.send("い")
subject.send("う")

まずはコードを動かして、それからその意味を理解していく、という順序で学ぶのが早いと考えています。

PublisherにSubjectを採用

Combineで非同期イベントを送信するものはPublisherと呼ばれます。まずはPublisherを知るのがCombineを知る第一歩です。上述の本では、最初のPublisherとして PassthroughSubject を採用しました。このやり方は、他の解説ではあまり見かけません。なぜSubjectを採用したのかを述べます。

Combineの解説でよく使われるPublisherのひとつは、NotificationCenter のPublisherです。

let myNotification = Notification.Name("MyNotification")
let publisher =
    NotificationCenter.default.publisher(for: myNotification)

publisher
    .sink { value in
        print("Received value:", value)
    }

NotificationCenter は知っている人が多く、導入として分かりやすいという利点があります。また、標準で publisher メソッドが用意されていて便利です。一方で欠点があります。単純なイベントしか発生させられないという点です。

Combineのイベントは以下の3種類があります。

  • イベント完了(.finished
  • エラー(.failure

これらを自由に発生させられるほうが学びやすいと考えます。

そこでSubjectの例を挙げます。

let subject = PassthroughSubject<String, MyError>()

subject.send("あ")
subject.send(completion: .finished)
subject.send(completion: .failure(.failed))

enum MyError: Error {
    case failed
}

3種類のイベントを簡単に発生させられるのがSubjectの利点です。この利点は、Xcode Playgroundでコードを書いて学ぶという方針に合致します。そのためSubjectを採用しました。

Subjectの注意点

Subjectの採用理由を述べましたが、注意すべき点もあります。

一般的なPublisherはイベントが流れてくるだけのものです。しかしSubjectは send でイベントを意図的に発生させることができます。便利な機能ですが、これはPublisherとしては余分な役割を持っているともいえます。

この点はSubjectがPublisherの例として良くない理由であり、他のCombineの解説でPublisherの導入にSubjectが採用されない理由です。上述の本では、Xcode Playgroundでコードを書いて学ぶという方針を重視したため、この点には目をつぶりました。

とはいえ、Subjectは実際のアプリ開発でよく使います。

Subjectを単なるPublisherとして見せる方法があります。

let subject = PassthroughSubject<String, Never>()
let publisher = subject.eraseToAnyPublisher()

型消去をおこない、AnyPublisher 型として見せることができます。イベント送信側では subject を使い、イベント受信側には publisher のほうを使わせるようにするわけです。実際のアプリ設計では、この方法を利用するのが好ましいです。

まとめ

Combineを学ぶにはXcode Playgroundを活用するのが良いです。SubjectはXcode Playgroundでの学びに向いています。ただし、一般的なPublisherと異なる点もあるので注意が必要です。

この記事は、Mobile Act ONLINE #2 で話した「Subject からはじめる Combine」を記事の形に改変したものです。

GitHubで編集を提案

Discussion