Search¶
This section explains how to implement online/offline search in iOS 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 SYOnlineSession.onlineMapsEnabled
switch.
Example¶
class DemoSearch {
let type = SYSearchSessionType.offline
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(type)
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 DemoReverseGeocoding {
let search = SYReverseSearch()
func reverseSearch() {
let coordinate = SYGeoCoordinate(latitude: 48.146410, longitude: 17.138270)
search.reverseSearch(with: coordinate, withFilter: nil) { (results: [SYReverseSearchResult]?, error) in
guard let results = results else {
print("SYReverseSearch error: \(String(describing: error))")
return
}
results.forEach { $0.printDescription() }
}
}
}
extension SYReverseSearchResult {
func printDescription() {
let description = resultDescription
print("""
\nSYReverseSearchResult:
country: \(description.countryIso)
city: \(String(describing: description.city))
street: \(String(describing: description.street))
house number: \(String(describing: description.houseNumber))
distance: \(distance)
""")
}
}