Skip to content

Search

This section explains how to implement online or offline geocoding and search into your Android application.

Autocomplete

The Sygic Maps SDK for iOS includes a Search API which provides functionality to search and obtain more information about places in the real world. Note that offline search is supported when a data connection is unavailable, if the data required to perform the search has been previously downloaded. Geocoding APIs resolve a free-formatted text query to an SYGeoCoordinates, while reverse geocoding APIs resolve from an SYGeoCoordinates to geographic data.

Warning

Despite the fact that many SYSearch instances can coexist at the same time, please note that each instance leaves some internal resources until the whole Sygic Maps SDK is terminated.

Info

The offline/online search is no longer handled by the onlineMapsEnabled switch.

Example

class DemoSearch {
    let search = SYSearch()
    var session: SYSearchSession?
    var results = [SYSearchAutocompleteResult]()

    func autocomplete() {
        let session = prepareValidSession() // reuse existing session, if it's valid

        let request = SYSearchRequest(query: "airport", location: SYGeoCoordinate(latitude: 48.142596, longitude: 17.125206))
        session.autocomplete(request) { (results: [SYSearchAutocompleteResult]?, status: SYSearchStatus) in
            guard status == .success, let results = results else { /* handle error */ return }

            // results are ready
            self.results = results
            results.forEach { (result) in
                self.printAutocompleteResult(result)
            }
        }
    }

    func geocodeLocation(autocompleteResultIndex index: Int) {
        // for geocodeLocation, it must be the same session, which returned that exact autocomplete result

        guard let session = session, session.isValid else { /* handle error */ return }
        guard let autocompleteResult = (index >= 0 && index < results.count ? results[index] : nil) else { return }
        guard let locationId = autocompleteResult.locationId else { return }

        let request = SYGeocodeLocationRequest(locationId: locationId)
        session.finish(byRequestingGeocodeLocation: request) { (result: SYSearchGeocodingResult?, status: SYSearchStatus) in
            guard status == .success, let result = result else { /* handle error */ return }

            // detailed result is ready
            self.printDetailedResult(result)
        }
    }

    func geocode() {
        let session = prepareValidSession() // reuse existing session, if it's valid

        let request = SYSearchRequest(query: "airport", location: SYGeoCoordinate(latitude: 48.142596, longitude: 17.125206))
        session.finish(byRequestingGeocode: request) { (results: [SYSearchGeocodingResult]?, status: SYSearchStatus) in
            guard status == .success, let results = results else { /* handle error */ return }

            // detailed results are ready
            results.forEach { (result) in
                self.printDetailedResult(result)
            }
        }
    }

    func prepareValidSession() -> SYSearchSession {
        if let session = session, session.isValid {
            return session
        } else {
            let session = search.startSession(.offline)
            self.session = session
            return session
        }
    }

    func printAutocompleteResult(_ result: SYSearchAutocompleteResult) {
        let title = result.title?.value ?? ""
        print("Autocomplete: \(title), \(result.type.rawValue)")
    }

    func printDetailedResult(_ result: SYSearchGeocodingResult) {
        let title = result.title?.value ?? ""
        let lat = result.location?.latitude ?? 0
        let lon = result.location?.longitude ?? 0
        print("GeocodingResult: \(title), \(result.type.rawValue); \(lat),\(lon)")

        if let mapResult = result as? SYSearchMapResult {
            // mapResult provides more specific info
        } else if let favoriteResult = result as? SYSearchFavoriteResult {
            // favoriteResult provides more specific info
        } // else if let ... SYSearch...Result
    }
}

Places

You can also search places around a specific coordinate in a radius or in a Bounding Box. Here's an example on how to do it.

Info

To request more places with the same request, use SYSearchMorePlacesSession

extension DemoSearch  {

    func placesRequestLocation() -> SYSearchPlacesRequest {
        let location = SYGeoCoordinate(latitude: 48.142596, longitude: 17.125206)
        let request = SYSearchPlacesRequest(location: location, radius: 10000, tags: [SYPlaceCategoryPetrolStation, SYPlaceCategoryPharmacy])
        request.maxResultsCount = 22
        return request
    }

    func placesRequestBoundingBox() -> SYSearchPlacesRequest {
        let box = SYGeoBoundingBox(bottomLeft: SYGeoCoordinate(latitude: 48.139466, longitude: 17.103821),
                                topRight: SYGeoCoordinate(latitude: 48.149452, longitude: 17.118079))
        let request = SYSearchPlacesRequest(boundingBox: box, tags: [SYPlaceCategoryRestaurant])
        request.maxResultsCount = 14
        return request
    }

    func places() {
        let session = prepareValidSession() // reuse existing session, if it's valid

        let request = placesRequestLocation() //or placesRequestBoundingBox()

        session.finish(byRequestingPlaces: request) {
            (places: [SYPlace]?, morePlacesSession: SYSearchMorePlacesSession?, status: SYSearchStatus) in

            guard status == .success, let places = places else { /* handle error */ return }

            // place results are ready
            places.forEach { (place) in
                self.printPlace(place)
            }

            // morePlacesSession can be saved and then used to get more places for the same request
        }
    }

    func printPlace(_ place: SYPlace) {
        print("")
        print("Place name: \(place.link.name); cat: \(place.link.category); gps: \(place.link.coordinate)")
        place.details.forEach { (arg0) in
            let (key, value) = arg0
            print("Place detail: \(key): \(value)")
        }
    }
}

Reverse Geocoding

Applications developed with the Sygic Maps SDK for iOS can perform offline and online geocoding, which allows geocode and reverse geocode requests to be performed event without an active data connection.

class SearchViewController: UIViewController {
    var reverseSearchResults: [SYReverseSearchResult] = []

    // Create an instance of SYReverseSearch
    let reverseSearch = SYReverseSearch()

    // Example of your method to perform reverse geocoding for specific coordinate
    func reverseSearch(at coordinate: SYGeoCoordinate) {

        // Perform request for coordinate
        self.reverseSearch.reverseSearch(with: coordinate) { [weak self] (reverseSearchResults, error) in
            self?.reverseSearchResults = reverseSearchResults

            // Example of accessing reverse geocoding results description
            if let firstResult = reverseSearchResults?.first {
                let resultDescription = firstResult.resultDescription // Contains textual description of the found result

                let countryIsoCode = resultDescription.countryIso
                let city = resultDescription.city
                let street = resultDescription.street
                let houseNumber = resultDescription.houseNumber
            }
        }
    }
}