Search code examples
iosgoogle-maps-api-3google-maps-sdk-ios

How to retrieve a PlaceID using a coordinate, name, and/or address?


I'm creating an iOS app and I want to offer the user the ability to choose which maps app to open up (Apple Maps or Google Maps). With Google maps, they're recommending using Maps Urls which is the safer and more solid route to go. Cool.

In my app, the user is already able to tap on locations on a map (I'm using the Apple Maps framework). So, I already have access to the coordinate, name, and address. I can use the Maps Url with just this info, however Google Maps will open up with just a pin at that exact location, which I don't want. By providing a PlaceID, Google Maps will open with the business selected, which is what I do want.

My question is what's the simplest way to retrieve the PlaceID? Can I just make an API call with the coordinate and get a response back with the placeID? Then, use that PlaceID in my constructed universal Maps Url to have Google Maps open at that business location?

Or maybe I'm complicating the whole thing?

Looking into Google's documentation. I've tried just using the coordinate. I am going to try using the coordinate plus a query with the business name. Just trying to provide the best experience. In my app, I want to stick with Apple Maps, but I also want the user to have the option to open a place in their preferred Maps Service if they want directions and other things.


Solution

  • I think I've found a way that I'm quite satisfied with. What I ended up doing is for the query I'm passing in the name + the address. This eliminates Google Maps from finding more locations with the same name close to the provided coordinate. Basically, I'm just adding more details to the query. Then I use the center parameter to pass in the coordinate.

    Looks like this:

    Quick Note:

    • selectedSearchResult is an MKMapItem coming from MapKit
    • placemark is a CLPlacemark
    // Function that builds the url
    private func googleMapsUrl() -> URL? {
        guard let mapItem = selectedSearchResult else { return nil }
        
        let coordinate = mapItem.placemark.coordinate
        let address = mapItem.placemark.title ?? ""
        let name = mapItem.name ?? ""
        
        let queryItems: [URLQueryItem] = [
            .init(name: "api", value: "1"),
            .init(name: "query", value: "\(name) \(address)"),
            .init(name: "center", value: "\(coordinate.latitude) \(coordinate.longitude)")
        ]
        var components = URLComponents(string: "https://www.google.com/maps/search/")
        components?.queryItems = queryItems
        
        return components?.url
    }
    

    Calling it from inside of a SwiftUI Button like this:

    if let url = googleMapsUrl(), UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url) { success in
            if success {
                print("Successfully opened url: \(url.absoluteString)")
            } else {
                print("Failed to open url: \(url.absoluteString)")
            }
        }
    }
    

    So far, works like a charm! I'm going to handle errors as well. I can tap on any MKMapItem, grab the name, address, and coordinate and use all of those together to form the query and Google Maps opens up right to that location with the name and everything. It doesn't just show a pin on the map which is what I was trying to avoid—explained by the docs under the Location Search section where they use CenturyLink Field as an example.