swiftmapkitmklocalsearchrequest

MapKit SearchResultsUpdating Not called


Can someone review my code? I'm trying to use MapKit to get local search results. I used this tutorial: https://www.thorntech.com/2016/01/how-to-search-for-location-using-apples-mapkit/

The differences from the tutorial and what I'm doing is that I don't want to display a mapView. I just want to click on button and a searchController pulls up that allows me to search for locations. The problem I'm having is that SearchResultsUpdating is not being called. Sorry for the long code, this is my first time using MapKit local search and I don't know what I'm missing.

*EDIT It's fixed. Attached it revised code.

import UIKit
import MapKit
import CoreLocation

class LocationSearchTable: UITableViewController {
let cellId = "cellId"
var searchController = UISearchController(searchResultsController: nil)

var matchingItems: [MKMapItem] = []
let mapView = MKMapView()
let locationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    setupLocationManager()
    setupSearchBar()
    setupMapView()

    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
    navigationController?.isNavigationBarHidden = false
    navigationItem.hidesSearchBarWhenScrolling = false
}

fileprivate func setupLocationManager() {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.requestLocation()
}

fileprivate func setupSearchBar() {
    let searchBar = searchController.searchBar
    searchBar.placeholder = "Enter Location"
    navigationItem.searchController = searchController
    searchController.searchResultsUpdater = self
    definesPresentationContext = true
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
    let selectedItem = matchingItems[indexPath.row].placemark
    cell.textLabel?.text = selectedItem.name
    cell.detailTextLabel?.text = ""
    return cell
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return matchingItems.count
}
}

extension LocationSearchTable: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == .authorizedWhenInUse {
        locationManager.requestLocation()
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location = locations.first {
        let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let region = MKCoordinateRegion(center: location.coordinate, span: span)
        mapView.setRegion(region, animated: true)
        print("location: \(location)")
    }
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print(error)
}
}

extension LocationSearchTable: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
    if let searchText = searchController.searchBar.text {
        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = searchText
        request.region = mapView.region

        let search = MKLocalSearch(request: request)
        search.start { (response, _) in
            guard let response = response else { return }
            self.matchingItems = response.mapItems
            self.tableView.reloadData()
        }
    }
}
}    

Solution

  • We try to make searchController work first.

    Follow this on setting up searchController

    1. Declare search controller, you've got this. let searchController = UISearchController(searchResultsController: nil)
    2. In viewDidLoad()
    navigationItem.searchController = searchController
    searchController.searchResultsUpdater = self
    definesPresentationContext = true
    
    1. Setup search controller text update, make sure your controller conforms to UISearchResultsUpdating protocol
    extension LocationSearchTable: UISearchResultsUpdating {
        func updateSearchResults(for searchController: UISearchController) {
            if let searchText = searchController.searchBar.text {
                print(searchText)
            }
        }
    }
    

    When we use UISearchController, we don't need setup searchBar.

    Comment below let me know search text can be printed out or not. Then we can continue.