iOS应用在本地搜索中被限制了

12
我正在实现自动完成(每添加一个新字符搜索一次)的功能,用于搜索地址的应用程序中,但是我一直收到MKErrorDomain错误3,即MKErrorLoadingThrottled。根据Apple dev,这个错误发生在以下情况下:
数据由于数据限制而未加载。如果应用程序在短时间内频繁请求数据,则可能会出现此错误。
我知道确切地有多少个请求被发送,每个搜索查询中的每个新字符都会发送一个请求(就像您期望自动完成一样)。当然,我打字速度很快,但仅在10或15个请求后就达到限制似乎很荒谬。查看以下两个源引用,我不明白为什么我一直受到限制。
根据Apple dev的说法:

每个应用或开发者ID没有请求限制,因此良好编写的应用程序应该不会遇到任何问题。然而,如果一个编写不良的应用程序创建了大量请求,则可能会出现限流。

而詹姆斯·霍华德在WWDC上说过:

我想谈论的另一件事是此API的使用限制。因此,我很高兴地宣布,没有应用程序或开发人员标识符的使用限制。因此,如果您拥有一个具有大量用户并且希望进行许多请求的应用程序,那就没问题。它会正常工作。我们执行的限流只是防止出现错误应用程序的第一道防线。因此,如果您将方向请求或本地搜索请求放在无限循环中,您就会遇到错误,最终将被限流。但是,如果您做一些合理的事情,比如说,响应用户输入时只进行方向操作,您可以进行一些这样的操作,因为我们已经展示了这个例子。例如,我们对一个用户输入进行了两次方向请求,这没问题。但是,如果每次用户点击屏幕时都进行10,000次请求,那么您将被限流。只要保持合理,您就不会有问题。

有什么想法为什么会发生这种情况吗?


3
我不会期望自动完成的工作方式是那样的。我希望先有一个初始请求,然后根据进一步的输入在内存中过滤这些结果。 - jrturton
从你的问题中并不清楚你在做什么。你是在搜索还是在进行地理编码(即将位置转换为地址,或根据地址查找位置)? - quellish
@quellish 我首先提到的是它搜索地址。另外,请看问题的标题。 - Daniel Larsson
MKLocalSearch用于搜索兴趣点、商家等。地理编码是查找地址或将地址转换为位置。您对“搜索地址”的描述似乎更像是地理编码而不是本地搜索。 - quellish
@quellish 我不知道这一点。我一直在使用MKLocalSearch,并删除那些带有商业ID的结果,以便只获取地址。最终我还是使用了Google Places。谢谢。 - Daniel Larsson
实际上,在iOS 7上,限制似乎是每分钟47个请求。 - Antonio Sesto
4个回答

12

自动完成需要特殊的API支持,MapKit并没有提供这样的接口。向普通搜索API发送大量请求会导致巨大的负载。

你基本上有两个选择:

  1. 使用Google Places。他们有一个专门的Places Autocompletion API。甚至在GitHub上还有完整的iOS库。

  2. 减少请求的数量,例如仅在用户停止输入300毫秒且没有早期请求时才发送请求。但这仍然不能保证苹果不会限制你的请求。


3
对我来说,方案二似乎是合乎逻辑的,而且在任何情况下都必须采取。 - Rivera
最终使用了一个名为SPGooglePlacesAutocomplete的Objective-C包装器来调用Google Places API,效果很好! - Daniel Larsson
选项2仍然会导致我的模拟器受到限制。 - Jameson
Mapkit现在已经有https://developer.apple.com/documentation/mapkit/mklocalsearchcompleter,自iOS 9.3以来就有了。相信这是在原始帖子之后引入的。 - daredevil1234

4

MKLocalSearch 主要用于在地图范围内查找兴趣点(例如企业等)。CLGeocoder 用于结构化地址和位置查询。

CLGeocoder 文档 指定 CLGeocoder 请求是有速率限制的,并提供了如何成为良好公民的指南。

特别需要注意的是指南中的第一条:“为任何用户操作最多发送一个请求”。这也适用于 MKLocalSearch,如果您同时有多个请求正在进行,那么您很可能会被限制速率。

实现起来相当容易:在发送新的 MKLocalSearchRequest 之前,取消任何待处理的请求。对于您所描述的自动完成功能而言,这非常有意义:如果用户正在输入第4个字符,则可能不需要第3个字符的请求或响应。


CLGeocoder和MKLocalSearch的结果不同。 - HotJard

2

在时间分析器工具中运行您的应用程序,查看您键入时调用该方法的次数。


最近我遇到了这个问题。结果发现我的代码在频繁调用API,导致系统崩溃。所以,请检查你的代码并进行清理。 - Lexo

1
我刚刚用Swift编写了一个Helper,以帮助使用苹果MapKit API进行建议搜索。当用户停止输入请求时,它会调用搜索请求。 https://github.com/ArniDexian/GeocodeHelper 使用方法非常简单:
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
        })
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接