.share()について
- ColdからHotに変換するオペレーター
- Observableを複数のサブスクライバーで共有することができる
public func share(replay: Int = 0, scope: SubjectLifetimeScope = .whileConnected) -> Observable<Element> {
switch scope {
case .forever:
switch replay {
case 0: return self.multicast(PublishSubject()).refCount()
default: return self.multicast(ReplaySubject.create(bufferSize: replay)).refCount()
}
case .whileConnected:
switch replay {
case 0: return ShareWhileConnected(source: self.asObservable())
case 1: return ShareReplay1WhileConnected(source: self.asObservable())
default: return self.multicast(makeSubject: { ReplaySubject.create(bufferSize: replay) }).refCount()
}
}
}
-
replay
: リプレイするイベントの最大キャッシュ数- 0の場合はリプレイされない
- 共通のサブスクライバーがいくつあって、何番目のサブスクライバーまでイベントを流すかによって値が変わる
-
scope
: 共有をいつまで続けるかのオプション-
.forever
: 一度サブスクライブすると永久的にアクティブになり、新たにサブスクライブされた場合もストリームが共有される- 一度取得した値を全ての画面やコンポーネントで使用する場合に使う
- アプリの設定情報など
-
.whileConnected
: アクティブなサブスクライバーが存在する間のみ有効- disposeされると全て解放される
-
.share()使用しないでサブスクライブした場合
let subject = PublishSubject<Int>()
let observable = subject
.debug("observable")
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー1: \(value)")
})
.disposed(by: bag)
// 1回目のイベントを発行
subject.onNext(1)
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー2: \(value)")
})
.disposed(by: bag)
// 2回目のイベントを発行
subject.onNext(2)
// --- 実行結果 ---
// observable -> subscribed
// observable -> Event next(1)
// サブスクライバー1: 1
// observable -> subscribed
// observable -> Event next(2)
// サブスクライバー1: 2
// observable -> Event next(2)
// サブスクライバー2: 2
Observableが2回サブスクライブされておりストリームが分離している
また2回目のonNextはサブスクライバー1には流れていない
.share()を使用してサブスクライブした場合
let subject = PublishSubject<Int>()
let observable = subject
.debug("observable")
.share()
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー1: \(value)")
})
.disposed(by: bag)
// 1回目のイベントを発行
subject.onNext(1)
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー2: \(value)")
})
.disposed(by: bag)
// 2回目のイベントを発行
subject.onNext(2)
// --- 実行結果 ---
// observable -> subscribed
// observable -> Event next(1)
// サブスクライバー1: 1
// observable -> Event next(2)
// サブスクライバー1: 2
// サブスクライバー2: 2
サブスクライバー2はサブスクライバー1と共通のObservableなのでストリームは分離していない
しかし、サブスクライバー2は1回目のonNextの後でサブスクライブしているので、1回目のonNextの値が流れてこない
.share(replay: 1)を使用した場合
let subject = PublishSubject<Int>()
let observable = subject
.debug("observable")
.share(replay: 1)
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー1: \(value)")
})
.disposed(by: bag)
// 1回目のイベントを発行
subject.onNext(1)
observable
.bind(to: Binder(self) { _, value in
print("サブスクライバー2: \(value)")
})
.disposed(by: bag)
// 2回目のイベントを発行
subject.onNext(2)
// --- 実行結果 ---
// observable -> subscribed
// observable -> Event next(1)
// サブスクライバー1: 1
// サブスクライバー2: 1
// observable -> Event next(2)
// サブスクライバー1: 2
// サブスクライバー2: 2
share(replay: 1)
を使用するとストリームのイベントがreplay: n
分キャッシュされて、後続のサブスクライバーがキャッシュされたイベントを受け取ることができる
そのため、サブスクライバー2は1回目のonNextの値を受け取ることができ、1つのストリームで同じ値を受け取ることができる