MKLocalSearch 请求给我奇怪的结果

MKLocalSearchRequest giving me weird results

所以我为我的地图应用程序实现了 searchBar,它给了我一些奇怪的结果。例如,如果我搜索 "Oslo",它会将我指向城市北部的一个非常具体但奇怪的地方并放大。一定是我在此处的代码中做错了什么。有人能发现问题吗?

// When user submits search query
func searchBarSearchButtonClicked(searchBar: UISearchBar){
    // resign first responder and dismiss the searchbar.
    searchBar.resignFirstResponder()
    dismissViewControllerAnimated(true, completion: nil)

    // Create and start search request
    localSearchRequest = MKLocalSearchRequest()
    localSearchRequest.naturalLanguageQuery = searchBar.text
    localSearch = MKLocalSearch(request: localSearchRequest)

    localSearch.startWithCompletionHandler { (localSearchResponse, error) -> Void in

        if localSearchResponse == nil{
            let alertController = UIAlertController(title: nil, message: "Place Not Found", preferredStyle: UIAlertControllerStyle.Alert)
            alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
            self.presentViewController(alertController, animated: true, completion: nil)
            return
        }

        let center = CLLocationCoordinate2D(latitude: localSearchResponse!.boundingRegion.center.latitude, longitude: localSearchResponse!.boundingRegion.center.longitude)
        self.updateCurrentMapRegion(center, distance: 5000)
        NSNotificationCenter.defaultCenter().postNotificationName("LocationUpdate", object: nil, userInfo: ["latitude": center.latitude, "longitude": center.longitude])
    }
}

此外,一个问题是我在获得搜索结果后更新地图区域时将距离硬编码为 5000 米。我怎样才能以更动态的方式处理这个问题?

使用 MKLocalSearchRequest() 的替代方法是什么,在我看来这听起来像是在寻找附近的东西而不是城市等更大的实体时应该使用的东西。

第一件事:MKLocalSearch 是您要使用的正确 API,即使您正在做的事情听起来有点奇怪!

MKLocalSearch 会为您提供一个位置列表,然后 returns 一个围绕这些位置的边界框,以最适合它认为您正在寻找的内容。我试过 运行 你的代码并为奥斯陆找到了这个:

您遇到的问题是您使用边界框的中心作为图钉位置,而不是奥斯陆地标。

所以这里不是你的代码行:

let center = CLLocationCoordinate2D(latitude: localSearchResponse!.boundingRegion.center.latitude,
    longitude: localSearchResponse!.boundingRegion.center.longitude)

您将使用:

let center = localSearchResponse?.mapItems.first?.placemark.coordinate

(这是一个可选的,但你可以选择如何处理它。我会告诉你我的首选方式。)

此外,这也解决了你关于放大到什么程度的问题。很简单,你可以使用区域的边界框作为缩放级别。我不确定您的 updateCurrentMapRegion:distance 方法是如何工作的,但 MKMapView 有方便的 setRegion:animated 方法供您使用(如果您有权访问)。

mapView.setRegion(localSearchResponse!.boundingRegion, animated: true)

综上所述,如果您有对 MapView 的引用,您应该能够用它替换完成块并让它工作:

guard let localSearchResponse = localSearchResponse, mapItem = localSearchResponse.mapItems.first else {
    let alertController = UIAlertController(title: nil, message: "Place Not Found", preferredStyle: UIAlertControllerStyle.Alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alertController, animated: true, completion: nil)
    return
}

let center = mapItem.placemark.coordinate
self.mapView.setRegion(localSearchResponse.boundingRegion, animated: true)
NSNotificationCenter.defaultCenter().postNotificationName("LocationUpdate", object: nil, userInfo: ["latitude": center.latitude, "longitude": center.longitude])

在此块中,我还将您的 if 语句替换为 guard 以设置两个值,因此我们不再需要强制解包选项。如果您无法使用此方法访问 mapView,您可以切换 updateCurrentMapRegion:center 以使其更适合,或者进行一些数学计算以使边界区域适合这些值。

您不应使用 MKLocalSearchRequest(),而应使用 MKLocalSearchCompleter,后者可提供更好的结果并在当前的 Apple 地图中使用。

您可以在
中了解如何实现它