# Swift - Combine - combineLatest

# What is it?

CombineLatest is an operator that combines more than one publishers, then provides a tuple of the latest value from each publisher.

The combined publisher doesn’t produce elements until each of its upstream publishers publishes at least one element.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732179378188/d42f519b-6bc3-43de-88d5-89214654ae60.png align="center")

# When to use?

When we want the downstream subscriber to receive the data of the most-recent element from more than one publishers.( when any of them emit a value.)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732179399507/ebbe6757-891f-4020-9e2b-a3f69c009ce5.png align="center")

# BMI Calculator example:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1732179537720/35abf1fb-5ca4-4e33-8563-a57686d467a2.png align="center")

```swift
            class BMIViewmOdel: ObservableObject {
    @Published var height: Double = 0
    @Published var weight: Double = 0
    @Published var bmi: Double = 0
    @Published var type: String = "Obese"
    
    private var cancellables = Set<AnyCancellable>()

    init() {
        
        Publishers.CombineLatest($height, $weight)
            .map { height, weight in
                let heightInMeters = height / 100
                return weight/(heightInMeters * heightInMeters)
            }
            .sink{ [weak self] (bmi: Double) in
                self?.bmi = bmi
                self?.updateType(bmi)
            }.store(in: &cancellables)
    }
    
    private func updateType(_ bmi: Double) {
        self.type = switch bmi {
        case ..<18.5: "Underweight"
        case 18.5..<24.9: "Normal"
        case 24.9..<29.9: "Overweight"
        default: "Obeese"
        }
    }
    
    
}

struct ContentView: View {
    @StateObject var viewModel : BMIViewmOdel = BMIViewmOdel()
    var body: some View {
        Form {
            Section("Input") {
                TextField("Height", value: $viewModel.height, format: .number, prompt: Text("Enter heigh"))
                TextField("Weight", value: $viewModel.weight, format: .number, prompt: Text("Enter the weight"))
            }
            
            Section("Result") {
                Text("BMI: \(viewModel.bmi)")
                Text("Category: \(viewModel.type)")
            }
            
        }  .navigationTitle("BMI Calculator")
    }
}
```

# Key items to note:

1\. Won't emit ANY values until ALL publishers have emitted at least once

2.After the initial values are received, CombineLatest maintains the most recent value from each publisher. (Even if it is a passthrough subject although passthrough subject does not hold the value. :) )
