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()
}
}
}
}
We try to make searchController
work first.
Follow this on setting up searchController
let searchController = UISearchController(searchResultsController: nil)
viewDidLoad()
navigationItem.searchController = searchController
searchController.searchResultsUpdater = self
definesPresentationContext = true
UISearchResultsUpdating
protocolextension 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.