# Publishers.CombineLatest

**제네릭 구조체** | 두 개의 Publisher로부터 최신의 요소를 전달받고 조합하는 Publisher

이니셜라이저는 조합할 두 개의 Publisher를 받는다.

조합할 모든 Publisher의 에러 타입은 같아야 한다.

두 개의 Publisher에서 최신의 요소를 발행했을 때 이들을 조합하는 동작을 원할 때 사용할 수 있다.

예를 들어 두 개의 입력 폼이 있고 모두 값이 입력되어야 버튼을 활성화해야 한다는 요구사항이 있을 때 이 동작을 사용할 수 있다. 두 개의 입력에 대한 Publisher에서 모두 값을 발행해야 하기 때문이다.

`comnbineLatest` 오퍼레이터와 관련이 있다.

```swift
let aSubject = PassthroughSubject<Int, Never>()
let bSubject = PassthroughSubject<Int, Never>()

// Publishers.CombineLatest Publisher
Publishers
  .CombineLatest(aSubject, bSubject)
  .sink(receiveCompletion: { completion in
    switch completion {
    case .failure:
      print("Combine CombineLatest Error")
    case .finished:
      print("Combine CombineLatest Finish")
    }
  }, receiveValue: { value in
    print("Combine CombineLatest : \(value)")
  })
  .store(in: &cancellables)

// Combine CombineLatest : (2, 3)
// Combine CombineLatest : (2, 4)
// Combine CombineLatest Finish

// combineLatest Operator
aSubject
  .combineLatest(bSubject)
  .sink(receiveCompletion: { completion in
    switch completion {
    case .failure:
      print("Combine CombineLatest Error")
    case .finished:
      print("Combine CombineLatest Finish")
    }
  }, receiveValue: { value in
    print("Combine CombineLatest : \(value)")
  })
  .store(in: &cancellables)

// Combine CombineLatest : (2, 3)
// Combine CombineLatest : (2, 4)
// Combine CombineLatest Finish

aSubject
  .combineLatest(bSubject) { $0 * $1 }
  .sink(receiveCompletion: { completion in
    switch completion {
    case .failure:
      print("Combine CombineLatest Error")
    case .finished:
      print("Combine CombineLatest Finish")
    }
  }, receiveValue: { value in
    print("Combine CombineLatest : \(value)")
  })
  .store(in: &cancellables)

// Combine CombineLatest : 6
// Combine CombineLatest : 8
// Combine CombineLatest Finish

// 1
aSubject.send(1)
// 2
aSubject.send(2)
// 3
bSubject.send(3)
// 4
bSubject.send(4)
```

두 개의 Subject로부터 최신의 요소를 전달받고 조합하도록 하였다.

변환 클로저를 적용하지 않은 코드는 다음과 같이 동작한다.

1. 1의 실행에 의해 `aSubject`에 1의 값을 전달한다. `bSubject`에 값이 전달된 적이 없으므로 해당 Publisher는 값을 내지 않는다.
2. 2의 실행에 의해 `aSubject`에 2의 값을 전달한다. `bSubject`에 값이 전달된 적이 없으므로 해당 Publisher는 값을 내지 않는다.
3. 3의 실행에 의해 `bSubject`에 3의 값을 전달한다. `aSubject`에 값이 전달된 적이 있으므로 해당 Publisher는 `aSubject`의 최신 값인 2와 `bSubject`의 최신 값인 3을 튜플의 형태로 조합하여 (2, 3)의 값을 낸다.
4. 4의 실행에 의해 `bSubject`에 4의 값을 전달한다. `aSubject`에 값이 전달된 적이 있으므로 해당 Publisher는 `aSubject`의 최신 값인 2와 `bSubject`의 최신 값인 4를 튜플의 형태로 조합하여 (2, 4)의 값을 낸다.

변환 클로저를 적용한 코드는 다음과 같이 동작한다.

1. 1의 실행에 의해 `aSubject`에 1의 값을 전달한다. `bSubject`에 값이 전달된 적이 없으므로 해당 Publisher는 값을 내지 않는다.
2. 2의 실행에 의해 `aSubject`에 2의 값을 전달한다. `bSubject`에 값이 전달된 적이 없으므로 해당 Publisher는 값을 내지 않는다.
3. 3의 실행에 의해 `bSunject`에 3의 값을 전달한다. `aSubject`에 값이 전달된 적이 있으므로 해당 Publisher는 `aSubject`의 최신 값인 2와 `bSubject`의 최신 값인 3을 곱하여 6의 값을 낸다.
4. 4의 실행에 의해 `bSunject`에 4의 값을 전달한다. `aSubject`에 값이 전달된 적이 있으므로 해당 Publisher는 `aSubject`의 최신 값인 2와 `bSubject`의 최신 값인 4를 곱하여 8의 값을 낸다.

## RxSwift

`combineLatest` 오퍼레이터를 사용하여 구현할 수 있다.

```swift
let aSubject = PublishSubject<Int>()
let bSubject = PublishSubject<Int>()

Observable.combineLatest(aSubject, bSubject)
  .subscribe(onNext: { value in
    print("RxSwift CombineLatest : \(value)")
  }, onError: { _ in
    print("RxSwift CombineLatest Error")
  }, onCompleted: {
    print("RxSwift CombineLatest Finish")
  })
  .disposed(by: disposeBag)

aSubject.onNext(1)
aSubject.onNext(2)
bSubject.onNext(3)
bSubject.onNext(4)

// RxSwift CombineLatest : (2, 3)
// RxSwift CombineLatest : (2, 4)
```

## ReactiveSwift

`combineLatest` 오퍼레이터를 사용하여 구현할 수 있다.

```swift
let aProperty = MutableProperty<Int>(0)
let bProperty = MutableProperty<Int>(0)

aProperty.signal
  .combineLatest(with: bProperty.signal)
  .observe { event in
    switch event {
    case let .value(value):
      print("ReactiveSwift CombineLatest : \(value)")
    case .failed:
      print("ReactiveSwift CombineLatest Error")
    case .completed:
      print("ReactiveSwift CombineLatest Finish")
    default:
      break
    }
  }

aProperty.value = 1
aProperty.value = 2
bProperty.value = 3
bProperty.value = 4

// ReactiveSwift CombineLatest : (2, 3)
// ReactiveSwift CombineLatest : (2, 4)
// ReactiveSwift CombineLatest Finish
```

## 참고

[ReactiveX - Operators - CombineLatest](http://reactivex.io/documentation/operators/combinelatest.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://presto95.gitbook.io/combine-rxswift-reactiveswift/publisher/combinelatest.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
