Why do I get an MKErrorDomain error when doing a local search?

2.1k Views Asked by At

I am trying to implement a search bar where the user can type in a string and search for an address or a business.

To find businesses I use Yelp APIs to outsource the information I need.

To find addresses I use Apple's MKLocalSearch APIs to get the information I need.

However, I do have a problem. When I hold on to the backspace button to clear out the text from the search bar or type too fast into the search bar I get an MKErrorDomain error:

The operation couldn’t be completed. (MKErrorDomain error 3.)

When I get this error I will have to wait a few moments in order for the code to work again and retrieve information from the APIs.

The following code is what I have to implement what I am looking for:

This is the search bar delegate method:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    if searchBar.text == "" {
        addServiceCellToTableView()
        loadSearchHistory()
        return
    } else if searchBar.text != "" {
        removeServiceCellFromTableView()
    }


    if searchCompleter.isSearching{
        searchCompleter.cancel()
        searchCompleter.region = (delegate?.businessSearchResultTableViewControllerNeedsUpdatedMapRegion(self))!
        searchCompleter.queryFragment = searchText
    } else {
        searchCompleter.region = (delegate?.businessSearchResultTableViewControllerNeedsUpdatedMapRegion(self))!
        searchCompleter.queryFragment = searchText
    }

}

I use MKLocalSearchCompleter to get suggestions based on what the user types into the search bar:

func completerDidUpdateResults(_ completer: MKLocalSearchCompleter){

    guard completer.results.count != 0 else {return}

    var searchTerm: String = completer.results.first!.title
    if completer.results.first!.subtitle != "" {
        searchTerm = searchTerm + ", " + completer.results.first!.subtitle
    }


    if let _ = addressDetector.firstMatch(in: searchTerm, options: [], range: NSMakeRange(0, searchTerm.utf8.count)){
        searchAddress(for: searchTerm)
    } else {
        getBusinesses(withSearchTerm: searchTerm, userCoordinates: currentUserLocation.coordinate)
    }


}

In the code above I use NSDataDetector to see if the suggested text is an address...If so I feed it into MKLocalSearch...

Finally, In order to search for for addresses I defined a method called searchAddress(for:):

func searchAddress(for string: String){

        let localSearchRequest = MKLocalSearchRequest()
        localSearchRequest.naturalLanguageQuery = string
        localSearchRequest.region = (delegate?.businessSearchResultTableViewControllerNeedsUpdatedMapRegion(self))!

        let localSearch = MKLocalSearch(request: localSearchRequest)
        localSearch.start(completionHandler: {searchResponse, error in
            guard error == nil else {
                print(error.debugDescription)
                return
            }

            guard let mapItems = searchResponse?.mapItems else {return}

            self.tableViewDataSourceList = mapItems
            self.tableView.reloadData()
            self.delegate?.businessSearchResultTableViewStopedGettingBusiness(self, with: self.tableViewDataSourceList, at: CLLocationCoordinate2D(latitude: self.currentUserLocation.coordinate.latitude, longitude: self.currentUserLocation.coordinate.longitude))
        })
    }

When I type too fast or hold on the backspace key I get the following error in the console:

The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)
The operation couldn’t be completed. (MKErrorDomain error 3.)

Any help will be much appreciated :-)

1

There are 1 best solutions below

5
On BEST ANSWER

What you're seeing here is the MKError.loadingThrottled error. You will have to delay requests you're sending to Apple.

You can do this by restarting a timer every time the user updates the search query. You can adjust how frequently you ping the API by extending the length of the timer. By resetting the timer each time the query is updated, you avoid sending multiple requests when the characters are changing rapidly.

// declare and store Timer somewhere

func searchAddress(with query: String) {

}

func timerDidFire(_ sender: Any) {
    let query = textField.text
    searchAddress(with: query)
}

Timer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(timerDidFire), userInfo: nil, repeats: false)