Skip to main content

Display search results within a bounding box on a map

This example uses the Mapbox Maps SDK for iOS. Add the Maps SDK as a dependency using the Maps SDK installation instructions.

ViewController
import UIKit
import CoreLocation
import MapboxMaps
import MapboxSearch

class MapboxBoundingBoxController: MapsViewController {
let searchEngine = CategorySearchEngine()

let mapboxSFOfficeCoordinate = CLLocationCoordinate2D(latitude: 37.7911551, longitude: -122.3966103)

var draggingRefreshTimer: Timer?

var mapDraggingSubscription: MapboxMaps.Cancelable?

let categoryName = "cafe"

var shouldSkipNextCameraChangedUpdate = false

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

updateSearchResults(proximity: mapboxSFOfficeCoordinate)

mapDraggingSubscription = mapView.mapboxMap.onEvery(.cameraChanged, handler: reloadResultsOnCameraChange(_:))
}

func updateSearchResults(proximity: CLLocationCoordinate2D? = nil, boundingBox: MapboxSearch.BoundingBox? = nil) {
/// Configure RequestOptions to perform search near the Mapbox Office in San Francisco

let requestOptions = SearchOptions(proximity: proximity, boundingBox: boundingBox)

searchEngine.search(categoryName: categoryName, options: requestOptions) { response in
do {
let results = try response.get()
self.showAnnotations(results: results)
} catch {
self.showError(error)
}
}
}

func reloadResultsOnCameraChange(_ event: Event) {
draggingRefreshTimer?.invalidate()
draggingRefreshTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(reloadResultInMapBounds), userInfo: nil, repeats: false)
}

@objc
func reloadResultInMapBounds() {
guard shouldSkipNextCameraChangedUpdate == false else {
shouldSkipNextCameraChangedUpdate = false
return
}
let cameraOptions = CameraOptions(cameraState: mapView.mapboxMap.cameraState, anchor: nil)
let cameraBounds = mapView.mapboxMap.coordinateBounds(for: cameraOptions)

let boundingBox = MapboxSearch.BoundingBox(cameraBounds.southwest,
cameraBounds.northeast)
updateSearchResults(boundingBox: boundingBox)
shouldSkipNextCameraChangedUpdate = true
}
}
MapsViewController
import UIKit
import MapboxMaps
import MapboxSearch
import MapboxSearchUI

class MapsSearchViewController: UIViewController {
var searchController = MapboxSearchController()
var mapView: MapView?
var annotationManager: PointAnnotationManager?

override func viewDidLoad() {
super.viewDidLoad()

// Search setup
searchController.delegate = self
let panelController = MapboxPanelController(rootViewController: searchController)
addChild(panelController)

// Map setup
let mapView = MapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.mapView = mapView
view.addSubview(mapView)

annotationManager = mapView.annotations.makePointAnnotationManager()
}

func showResults(_ results: [SearchResult]) {
let annotations = results.map { searchResult -> PointAnnotation in
var annotation = PointAnnotation(coordinate: searchResult.coordinate)
annotation.textField = searchResult.name
annotation.textOffset = [0, -2]
annotation.textColor = ColorRepresentable(color: .red)
annotation.image = .default
return annotation
}

annotationManager?.syncAnnotations(annotations)
if case let .point(point) = annotations.first?.feature.geometry {
let options = CameraOptions(center: point.coordinates)
mapView?.mapboxMap.setCamera(to: options)
}
}
}

extension MapsSearchViewController: SearchControllerDelegate {
func categorySearchResultsReceived(results: [SearchResult]) {
showResults(results)
}

func searchResultSelected(_ searchResult: SearchResult) {
showResults([searchResult])
}

func userFavoriteSelected(_ userFavorite: FavoriteRecord) {
showResults([userFavorite])
}
}
Was this example helpful?