swiftgoogle-mapsmapkitmkmapview

Get location information MapKit Swift


I have some code that can query nearby locations based on some query string. Searching for a specific restaurant or place will yield results in the format below. If I am searching for a restaurant for example, how can I get more information about the location such as image, open hours, etc? Is there a way to use some native Swift API for this? Or is using google maps API the next best alternative?

<MKMapItem: 0x301095d00> {
    isCurrentLocation = 0;
    name = "Chick-fil-A";
    phoneNumber = "+1 (707) 421-9631";
    placemark = "Chick-fil-A, 1750 Travis Blvd, Fairfield, CA  94533, United States @ <+38.25884980,-122.05986700> +/- 0.00m, region CLCircularRegion (identifier:'<+38.25884981,-122.05986700> radius 141.17', center:<+38.25884981,-122.05986700>, radius:141.17m)";
    timeZone = "America/Los_Angeles (PDT) offset -25200 (Daylight)";
    url = "https://www.chick-fil-a.com/locations/ca/fairfield-in-line-dt";}
import MapKit
import CoreLocation

class AddressSearchViewModel: NSObject, ObservableObject, MKLocalSearchCompleterDelegate {
    @Published var searchResults: [searchLoc] = []
    @Published var searching: Bool = false
    private var searchCompleter: MKLocalSearchCompleter!
    
    override init() {
        super.init()
        
        searchCompleter = MKLocalSearchCompleter()
        searchCompleter.delegate = self
        searchCompleter.resultTypes = [.address, .pointOfInterest]
    }
    
    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
        getCityList(results: completer.results) { cityResults in
            DispatchQueue.main.async {
                self.searching = false
                cityResults.forEach { element in
                    if !self.searchResults.contains(where: { $0.searchName == element.searchName }) {
                        self.searchResults.insert(element, at: 0)
                    }
                }
            }
        }
    }
    
    func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) { }
    
    func performSearch(queryStr: String) {
        searching = true
        self.searchCompleter.queryFragment = queryStr
    }
    
    private func getCityList(results: [MKLocalSearchCompletion], completion: @escaping ([searchLoc]) -> Void) {
        var searchTemp: [searchLoc] = []
        let dispatchGroup = DispatchGroup()
        
        for result in results {
            dispatchGroup.enter()
            
            let request = MKLocalSearch.Request(completion: result)
            let search = MKLocalSearch(request: request)
            
            search.start { (response, error) in
                defer {
                    dispatchGroup.leave()
                }
                
                guard let response = response else { return }
                
                for item in response.mapItems {
                    if let name = item.name {
                        searchTemp.append(searchLoc(searchName: name, lat: item.placemark.coordinate.latitude, long: item.placemark.coordinate.longitude))
                    }
                }
            }
        }
        dispatchGroup.notify(queue: .main) {
            completion(searchTemp)
        }
    }
}

Solution

  • Apple has no API to give you data like opening hours, and images up to iOS 18.

    If it is enough for you, since iOS 18, Apple has an API to display images, openingHours and more to the user: see https://developer.apple.com/wwdc24/10097 at timestamp 6:12

    Be aware, that only the user sees this information, you as the app developer don't get the data, so you have no chance to mix this data with your own data.

    And on each of those Views, there is a link to Apples Maps app, that encourages the user to leave you app and go to Apples Maps app.

    Google: read the license conditions very carefully: for some data Google only allows to display google data only on Google Maps, and nowhere else. And outside Android, Google wants money.

    If you want more, you have to search somewhere else for this data. That would be too broad for a Stackoverflow answer.