12

I am implementing autocomplete (one search per new character added) in an app that searches for addresses, and I keep getting MKErrorDomain error 3, which is MKErrorLoadingThrottled. This error, according to Apple dev, occurs when

The data was not loaded because data throttling is in effect. This error can occur if an app makes frequent requests for data over a short period of time.

I know exactly how many requests are being made, one for each new charachter in the search query (just like you would expect autocomplete to work). Sure, I am a fast typer, but being able to hit the limit after just 10 or 15 requests seems absurd. Looking at the following two source references, I do not understand why I keep getting throttled.

According to Apple dev:

There are no request limits per app or developer ID, so well-written apps that operate correctly should experience no problems. However, throttling may occur in a poorly written app that creates an extremely large number of requests.

and as James Howard said at a WWDC:

And the other thing I want to talk about is the Usage Limits on this API. So, I'm happy to announce that there's no application or developer identifier wide usage limits. So, if you have a app that has a lot of users and you want to do a lot of requests, that's fine.

It'll work.

And the throttling that we do have is really just a first line of defense against buggy apps. So, if you put directions requests or local search requests in an infinite loop, you've got a bug, eventually you're going to get throttled.

But if you do something reasonable, you say oh, I'm going to just do directions in response to user input and you know you can do a few of those because we showed them that example.

Like we did two directions request in response to one user input, that's fine. But, you know if you're doing 10,000 every time the user taps on the screen, then you're going to get throttled. But, just keep it reasonable and you'll be fine.

Any ideas to why this is happening??

Daniel Larsson
  • 6,278
  • 5
  • 44
  • 82
  • 3
    I wouldn't expect autocomplete to work like that. I'd expect an initial request and then to filter those results in-memory based on further input. – jrturton May 10 '14 at 15:08
  • It's not clear from your question what you are doing. Are you searching, or are you geocoding (i.e. turning a location into an address, or finding a location based on an address). – quellish May 13 '14 at 07:57
  • @quellish The first thing I mention is that it searches for addresses. Also, see the title of the question. – Daniel Larsson May 13 '14 at 08:27
  • MKLocalSearch is for searching for *points of interest*. Businesses, etc. Geocoding is finding addresses, or turning addresses into locations. Your description of "searching for addresses" seems to describe geocoding rather than local search. – quellish May 13 '14 at 08:32
  • @quellish I did not know that. I was using MKLocalSearch and removing those with a business ID in order to get only addresses. I ended up using Google Places anyway. Thank you. – Daniel Larsson May 13 '14 at 08:35
  • Actually on iOS 7 the limit seems to be 47 requests per minute. – Antonio Sesto Jul 31 '14 at 15:04

4 Answers4

12

Autocompletion requires a special APIs. MapKit doesn't offer such an interface. Just firing off dozens of requests to the normal search API causes a tremendous load.

You basically have two options:

  1. Go with Google Places. They have a dedicated Places Autocompletion API. There is even a complete library for iOS on GitHub.

  2. Reduce the number of requests, e.g. by only sending a request if the user has paused typing for 300ms and only if no earlier request is outstanding. But that's still no guarantee that Apple won't throttle your requests.

Torino
  • 588
  • 2
  • 9
4

MKLocalSearch is primarily intended for finding points of interest (businesses, etc.) within a map's bounds. CLGeocoder is for structured address and location lookups.

The CLGeocoder documentation specifies that CLGeocoder requests are rate limited, and the documentation provides guidance on how to be a good citizen.

Of particular note is the first item in the guidelines: "Send at most one request for any user action". This should be applied to MKLocalSearch as well - if you have multiple requests in flight at the same time, you are VERY likely to get throttled.

This is actually pretty easy to implement: Before a new MKLocalSearchRequest is sent, cancel any pending requests. This makes a lot of sense for implementing autocomplete like you describe: if the user is entering the 4th character, you probably don't need the request or response for the 3rd character.

quellish
  • 21,123
  • 4
  • 76
  • 83
2

Run your app in the Time Profiler Instrument an see how many calls to that method are being made when you type.

Kirby Todd
  • 11,254
  • 3
  • 32
  • 60
  • This problem happened to me recently. It turned out that my code was thrashing thereby making multiple api calls. So, check your code and clean it up. – Lexo Jun 17 '23 at 20:14
1

I'm just wrote Helper on Swift to help make suggests with Apple MapKit API. It's call search request when user stop typing request. https://github.com/ArniDexian/GeocodeHelper

The usage is pretty simply:

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    GeocodeHelper.shared.decode(searchText.trimmed(), completion: { [weak self](places) -> () in
        self?.dataSource.locations = places
        self?.tableView.reloadData()
        return
        })
}
HotJard
  • 4,598
  • 2
  • 36
  • 36