share
- 하나의 upstream publisher의 output을 여러 subscriber들이 공유할 수 있도록 해준다.
Example 1
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
fatalError("Invalid URL")
}
let request = URLSession.shared.dataTaskPublisher(for: url).map(\.data).print().share()
let subscription1 = request.sink(receiveCompletion: { _ in }, receiveValue: {
print("Subscription 1")
print($0)
})
let subscription2 = request.sink(receiveCompletion: { _ in }, receiveValue: {
print("Subscription 2")
print($0)
})
Output 1
receive subscription: (DataTaskPublisher)
request unlimited
receive value: (27520 bytes)
Subscription 1
27520 bytes
Subscription 2
27520 bytes
receive finished
- Output을 공유하기 때문에 요청은 한번만 수행된다.
Example 2
let pub = (1...3).publisher
.delay(for: 1, scheduler: DispatchQueue.main)
.map( { _ in return Int.random(in: 0...100) } )
.print("Random")
.share()
let cancellable1 = pub
.sink { print ("Stream 1 received: \($0)")}
let cancellable2 = pub
.sink { print ("Stream 2 received: \($0)")}
Output 2
Random: request unlimited
Random: receive value: (18)
Stream 1 received: 18
Stream 2 received: 18
Random: receive value: (94)
Stream 1 received: 94
Stream 2 received: 94
Random: receive value: (10)
Stream 1 received: 10
Stream 2 received: 10
Random: receive finished
- Output을 공유하기 때문에 일정한 랜덤값을 받는다. (공유하지 않는다면 각각 다른 랜덤값을 받아올 것이다.)
multicast
- 하나의 Output을 전달하는 subject를 여러 subscriber에게 제공한다.
- 즉, 각각 subscriber들이 값을 전달받는 용도의 subject를 갖게되면서 이를 통해 하나의 전달값을 동시에 받아올 수 있게 되는 것이다.
- 여러 downstream subscriber가 있어도, publisher는 한번만 값을 발행한다. 따라서 값을 발행하는 과정에서 부하가 큰 작업(네크워크 요청 등)에 유용하게 사용할 수 있다.
- 이렇게 publisher는 ConnectablePublisher이기 때문에 connect() 메서드를 수행해야 값 발행을 시작한다.
- multicast(_:) 는 클로저를 받아 각각의 Subject에게 다른 Subject를 제공하지만, multicast(subject:)는 하나의 단일 Subject를 제공한다는 것이 다르다.
Example
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
fatalError("Invalid URL")
}
let subject = PassthroughSubject<Data, URLError>()
let request = URLSession.shared.dataTaskPublisher(for: url).map(\.data).print().multicast(subject: subject)
let subscription1 = request.sink(receiveCompletion: { _ in }, receiveValue: {
print("Subscription 1")
print($0)
})
let subscription2 = request.sink(receiveCompletion: { _ in }, receiveValue: {
print("Subscription 2")
print($0)
})
let subscription3 = request.sink(receiveCompletion: { _ in }, receiveValue: {
print("Subscription 3")
print($0)
})
let cacellalbe = request.connect()
Output
receive subscription: (DataTaskPublisher)
request unlimited
receive value: (27520 bytes)
Subscription 2
27520 bytes
Subscription 3
27520 bytes
Subscription 1
27520 bytes
receive finished
- 각각의 subscriber가 한번의 작업만으로 값들을 받아옴을 알 수 있다.
- cf. 물론 값 전달용도로 생성한 subject에도 값을 발행할 수 있다. 이 경우에도 모든 subscriber가 값을 한번에 받는다.
'🍎 Apple > Combine & Rx' 카테고리의 다른 글
[RxSwift] Subject (0) | 2022.02.16 |
---|---|
[RxSwift] Observable & Operator (0) | 2022.02.14 |
[Combine] timer (by Runloop, Timer Class, DispatchQueue) (2) | 2022.01.13 |
[Combine] Operator (4): Sequence Operator (0) | 2022.01.12 |
[Combine] Operator (3): Combining Operator (0) | 2022.01.12 |