Why is MKLocalSearch for "nearby restaurants" returning locations in different cities?

1k Views Asked by At

I'm building a a simple application that allows a user to save their location for later.

The Goal: A user pins their address when at a business, and we save the name of the business

My approach: I'm requesting the location from a locationManager. Then I reverse geocode the CLLocation into a CLPlacemark. Since the placemark isn't recognizing the business name, I start a MKLocalSearch for "restaurants nearby". The response.mapItems are returning locations in completely different cities.

I have specified the region and verified that the placemark is correctly returning the user's address. So, I believe the issue lays within the MKLocalSearch.

Why does it return results for different cities?

Updated: All code From View Controller

class ViewController: UIViewController {

    let locationManager = CLLocationManager()
    var places = [MKMapItem]()

    let naturalLanguageQuery = "closest places to eat"
    let queries = ["restaurants", "places to eat", "breakfast", "lunch", "dinner"]

    override func viewDidLoad() {
        super.viewDidLoad()
        //  Do any additional setup after loading here
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if CLLocationManager.authorizationStatus() == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
        }
    }

    @IBAction func getLocation() {
        if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
    }

    func add(placemark: CLPlacemark) {
        search(placemark: placemark, index: self.queries.count - 1)
    }

    func searchCompleted(placemark: CLPlacemark) {
        guard let foo = Scraper.shared.sortByDistance(userPlacemark: placemark, items: places) else { return }
        for item in Scraper.shared.filterForUnique(items: foo) {
            print(item)
            if item.placemark.addressString == placemark.addressString {

            }
        }
    }

    func search(placemark: CLPlacemark, index: Int) {
        let request = MKLocalSearchRequest()
        guard let coordinate = placemark.location?.coordinate else { return }
        request.region = MKCoordinateRegionMakeWithDistance(coordinate, 1600, 1600)
        request.naturalLanguageQuery = queries[index]
        MKLocalSearch(request: request).start { (response, error) in
            guard error == nil else { return }
            guard let response = response else { return }
            guard response.mapItems.count > 0 else { return }

            for item in response.mapItems {
                self.places.append(item)
            }

            if index != 0 {
                self.search(placemark: placemark, index: index - 1)
            } else {
                self.searchCompleted(placemark: placemark)
            }
        }
    }
}

extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let geocoder = CLGeocoder()
        if let loc = locations.last {
            geocoder.reverseGeocodeLocation(loc) { (placemarks, error) in
                if let error = error {
                    print("error")
                } else {
                    if let placemark = placemarks?.first {

                        print(placemark.debugDescription)
                        self.add(placemark: placemark)
                    }
                }
            }
        }
    }

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

There are 1 best solutions below

0
binaryPilot84 On BEST ANSWER

Given your code, it appears your logic is correct, but depending on the location, you may not get what you want. Apple's documentation for the MKCoordinateRegion states that "specifying a region does not guarantee that the results will all be inside the region. It is merely a hint to the search engine." MKLocalSearch Documentation