> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/ios/maps/llms.txt)

# Combine

![Shows how to use map events with Combine framework.](https://docs.mapbox.com/ios/assets/ideal-img/maps-examples-combine.f808414.480.png)

This example demonstrates how to use [Map events](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/events/) in conjunction with the [Combine framework](https://developer.apple.com/documentation/combine/) for handling map-related events in an iOS app. The code showcases the usage of Combine publishers to react to events, specifically the camera changes on the **Mapbox Maps SDK for iOS**. The [`MapView`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/map-view/) instance listens for camera changes using the [`onCameraChanged`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/map/oncamerachanged(action:)/) event signal and processes them with Combine functionalities. The camera state data retrieved from the event is then displayed in a formatted manner on a `UILabel` within the view.

The implementation includes setting up the `MapView`, subscribing to camera change events, updating the camera label with the relevant map information, and incorporating Combine's powerful capabilities seamlessly into mapping interactions. By combining `MapboxMaps`, Combine publishers, and UIKit components, developers can efficiently manage and respond to map events using reactive programming paradigms in their iOS applications.

> **Note: iOS Examples App Available**
> 
> This example code is part of the **Maps SDK for iOS Examples App**, a working iOS project [available on Github](https://github.com/mapbox/mapbox-maps-ios/tree/11.33.0/Sources/Examples). iOS developers are encouraged to run the examples app locally to interact with this example in an emulator and explore other features of the Maps SDK.
> 
> See our [Run the Maps SDK for iOS Examples App](https://docs.mapbox.com/help/tutorials/maps-sdk-ios-examples-app/) tutorial for step-by-step instructions.

**Swift**

Title: `CombineExample.swift`

[View on GitHub](https://github.com/mapbox/mapbox-maps-ios/blob/main/Sources/Examples/All%20Examples/Lab/CombineExample.swift)

```swift
import UIKit
import MapboxMaps
import Combine

/// This examples shows how to use Map events with Combine framework.
final class ViewController: UIViewController {
    private var mapView: MapView!
    private var tokens = Set<AnyCancellable>()
    private let cameraLabel = UILabel.makeCameraLabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        mapView = MapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(mapView)

        cameraLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(cameraLabel)
        cameraLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -24).isActive = true
        cameraLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        // The on-prefixed event signals can be used as publishers:
        mapView.mapboxMap.onCameraChanged
            .debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
            .map(\.cameraState)
            .print("Camera State")
            .sink { [weak self] state in
                self?.cameraLabel.attributedText = .formatted(cameraSate: state)
                self?.cameraLabel.setNeedsLayout()
            }
            .store(in: &tokens)
    }

    
}

private extension UILabel {
    static func makeCameraLabel() -> UILabel {
        let label = UILabel()
        label.numberOfLines = 0
        label.backgroundColor = UIColor.systemBackground
        label.layer.cornerRadius = 5
        label.layer.masksToBounds = true
        return label
    }
}

private extension NSAttributedString {
    static func logString(_ text: String, bold: Bool = false) -> NSAttributedString {
        var attributes = [NSAttributedString.Key: Any]()
        attributes[.font] = UIFont.monospacedSystemFont(ofSize: 13, weight: bold ? .bold : .regular)
        return NSAttributedString(string: text, attributes: attributes)
    }

    static func formatted(cameraSate: CameraState) -> NSAttributedString {
        let str = NSMutableAttributedString()
        str.append(.logString("lat:", bold: true))
        str.append(.logString(" \(String(format: "%.2f", cameraSate.center.latitude))\n"))
        str.append(.logString("lon:", bold: true))
        str.append(.logString(" \(String(format: "%.2f", cameraSate.center.longitude))\n"))
        str.append(.logString("zoom:", bold: true))
        str.append(.logString(" \(String(format: "%.2f", cameraSate.zoom))"))
        if cameraSate.bearing != 0 {
            str.append(.logString("\nbearing:", bold: true))
            str.append(.logString(" \(String(format: "%.2f", cameraSate.bearing))"))
        }
        if cameraSate.pitch != 0 {
            str.append(.logString("\npitch:", bold: true))
            str.append(.logString(" \(String(format: "%.2f", cameraSate.pitch))"))
        }
        return str
    }
}
```