Directory
You can search for objects in the Urbi directory, handle search results, and use suggestions to refine search queries. The directory contains information about objects of the following types:
- companies and their branches
- buildings
- parking lots
- public transport stops and metro stations
- roads (streets, intersections, highways)
- settlements of various sizes (countries, cities, regions, villages, etc.)
- various area objects (parks, beaches, etc.)
See the full list of available object types in the ObjectType class description.
To start working with the directory:
- Create a search engine.
- Build a search query.
- Get, handle, and display search results.
Creating a search engine
To search for objects in the directory, create a SearchManager object and call one of the methods that determines the directory operating mode:
- SearchManager.createOnlineManager() - creates an online directory.
- SearchManager.createOfflineManager() - creates an offline directory (preloaded data only).
- SearchManager.createSmartManager() - creates a combined directory that works primarily with online data and switches to offline mode when the network goes down.
Important
Some methods work only in a specific directory mode.
Example of creating a search engine with an online directory:
let searchManager = SearchManager.createOnlineManager(context: sdk.context)
Building a search query
To send a search query, create a SearchQuery object using the SearchQueryBuilder and pass it to the search() method.
Any search query must contain three logical components:
-
Object search request (what to search for?). You can formulate the request using one of the methods below:
-
From a text string using the fromQueryText() method. You can formulate a text request to search for a specific object (
The Dubai Frame
) or to get a list of multiple objects by a criterion (musical instrument stores
). -
By category IDs using the fromRubricIds() method or in combination with a text string using the fromQueryTextAndRubricIds() method. This method is useful for creating a selection of objects of a specific type.
-
By ID of:
- Organizations using the fromOrgId() method. If a company has multiple branches, all locations will be listed in the response.
- Buildings using the fromBuildingId() method.
- Any object using the searchById() method of the search engine.
-
-
Geographic restriction (where to search?). You can limit the search area using one of the methods below:
-
Search within a polygon: specify coordinates using the setSpatialRestriction() method.
-
Search in a rectangular area of interest: specify coordinates using the setAreaOfInterest() method. This method sets a priority search area but does not strictly limit the search: if no results are found within the area of interest, the search will continue outside the area.
-
Search within a radius around a point: specify the search center using the setGeoPoint() or fromGeoPoint() method and, if necessary, the search radius using the setRadius() method.
The fromGeoPoint() method works only in online search mode.
-
Arbitrary query: if the object search query is formulated using the fromQueryText() method, you can also specify the geographical restriction in the same text (
flowers near the Burj Khalifa
).
-
-
(Optional component) Additional restrictions on search results using one or more of the methods below:
- Search for objects of a specific type only: list the object types you are interested in using the setAllowedResultTypes() method (for example, buildings only).
- Filter results: specify a filtering criterion using the setDirectoryFilter() method (for example, by working hours).
- Sort results: specify a sorting criterion using the setSortingType() method (for example, by rating).
- Number of results per page: set a limit using the setPageSize() method.
- Locale for the search query: specify the language and region using the setLocale() method.
Examples
-
Find Italian cuisine restaurants in the Jumeirah district of Dubai that are currently open, sorted by rating:
// Create a filter for working hours let filter = DirectoryFilter( workTime: .openNow // keep only currently open objects ) let searchQuery = SearchQueryBuilder .fromQueryText(queryText: "Italian restaurants in Jumeirah Dubai") .setDirectoryFilter(filter: filter) // filter by working hours .setSortingType(sortingType: .byRating) // sort by rating .setPageSize(pageSize: 10) // maximum 10 objects per results page .build()
-
Find all parking lots within a 1 km radius, sorted by distance:
let searchQuery = SearchQueryBuilder .setAllowedResultTypes(allowedResultTypes: [.parking]) // parkings only .setGeoPoint(geoPoint: GeoPoint(latitude: 59.936, longitude: 30.351)) // search center .setRadius(radius: Meter(value: 1000)) // search radius .setSortingType(sortingType: .byDistance) // sort by distance .build()
-
Find all settlements (cities, villages, towns, etc.) within a polygon:
// Create a search area as a polygon let polygon = [ GeoPoint(latitude: 55.751244, longitude: 37.618423), GeoPoint(latitude: 55.760244, longitude: 37.628423), GeoPoint(latitude: 55.770244, longitude: 37.618423), GeoPoint(latitude: 55.751244, longitude: 37.608423)] let searchQuery = SearchQueryBuilder .setAllowedResultTypes(allowedResultTypes: [.admDivCity, .admDivSettlement]) // cities and small settlements only .setSpatialRestriction(spatialRestriction: polygon) // search area .build()
-
Find all objects that provide document printing services in an area of interest:
// Create a rectangular area of interest using the coordinates of two corners let areaOfInterest = GeoRect( southWestPoint: GeoPoint(latitude: 59.931, longitude: 30.344), // southwest corner northEastPoint: GeoPoint(latitude: 59.936, longitude: 30.351) // northeast corner ) let searchQuery = SearchQueryBuilder .fromQueryText(queryText: "document printing") .setAreaOfInterest(rect: areaOfInterest) .build()
-
Find all companies at the address "Trade Center 1, Jumeirah, Dubai":
let searchQuery = SearchQueryBuilder .fromQueryText(queryText: "Trade Center 1, Jumeirah, Dubai") .setAllowedResultTypes(allowedResultTypes: [.branch]) // companies only .setPageSize(pageSize: 10) // maximum 10 objects per results page .build()
-
Find all branches of a company by a known ID:
let id = 70000001033047305 let searchQuery = SearchQueryBuilder .fromOrgId(orgId: id) .build()
-
Find a specific object by a known ID:
let id = 13933647002594323 searchManager.searchById(id: id).sink { object in print(object?.title) }
Geocoding
With the SDK, you can do geocoding tasks: determine coordinates of an object on the map by its address (direct geocoding) and vice versa, to determine the address of an object on the map by its coordinates (reverse geocoding).
Direct geocoding
To get the coordinates of an object by its address, create a search query specifying the following details:
-
The address in the text query using the fromQueryText() method.
For more accurate search results, specify the city (village, district, region) where the search should be performed. The locality name should be specified along with the name of the region.
-
(Recommended) The type of object whose coordinates you want to obtain using the setAllowedResultTypes() method.
For example, to get the coordinates of a building at the address "171, Jumeirah road, Dubai":
let searchQuery = SearchQueryBuilder
.fromQueryText(queryText: "171, Jumeirah road, Dubai")
.setAllowedResultTypes(allowedResultTypes: [.building])
.build()
In the search result, you will receive a DirectoryObject. The coordinates of the object are presented in the markerPosition
field as a GeoPointWithElevation object. Example:
markerPosition:
GeoPointWithElevation(
latitude: Latitude(value: 25.21653),
longitude: Longitude(value: 55.252752),
elevation: Elevation(value: 0.0)
),
See more about other information in search results at the Object data structure section.
Reverse geocoding
To get the address of an object by its coordinates, create a search query specifying the object coordinates using the setGeoPoint() or fromGeoPoint() method.
For example, to find the address of an object at the coordinates 25.21653, 55.252752
:
let searchQuery = SearchQueryBuilder
.fromGeoPoint(geoPoint: GeoPoint(latitude: 25.21653, longitude: 55.252752))
.build()
In the search result, you will receive a DirectoryObject. The address of the object is presented in the address
field as an Address object. Example:
address:
Address(
drillDown: [
AddressAdmDiv(type: .country, name: "UAE"),
AddressAdmDiv(type: .region, name: "Dubai Emirate"),
AddressAdmDiv(type: .districtArea, name: "Dubai Municipality"),
AddressAdmDiv(type: .city, name: "Dubai"),
AddressAdmDiv(type: .division, name: "Jumeirah"),
AddressAdmDiv(type: .district, name: "Jumeirah 1")
],
components: [
AddressComponent(AddressStreet(street: "Jumeirah road", number: "171", fiasCode: nil))
],
buildingName: "Mercato Mall",
buildingId: BuildingId(value: 13933647002354225),
postCode: nil,
buildingCode: nil,
fiasCode: nil,
addressComment: "G Floor, Shop VS1"
),
See more about other information in search results at the Object data structure section.
Modifying search parameters
You can modify or add parameters to an already created search query. To do this, create a new SearchQuery object, specify the existing query using the fromQuery() method, and specify the parameters to be additionally applied. For example, change the sorting type for parking lot searches:
// Create the initial query
let searchQuery = SearchQueryBuilder
.fromGeoPoint(geoPoint: GeoPoint(latitude: 59.936, longitude: 30.351))
.setRadius(radius: Meter(value: 1000))
.setAllowedResultTypes(allowedResultTypes: [.parking])
.setSortingType(sortingType: .byDistance) // sort by distance
.build()
// Create a new query with a different sorting type
let searchQueryUpdated = SearchQueryBuilder
.fromQuery(query: searchQuery) // reference the initial query
.setSortingType(sortingType: .byRating) // sort by rating
.build()
The other parameters of the initial query remain unchanged.
Getting search results
Calling the search() method returns a deferred SearchResult, which contains a paginated list of found objects (DirectoryObject):
searchManager.search(query: searchQuery).sink{ searchResult in
// Get the first object of the first page
let directoryObjectTitle = searchResult.firstPage?.items?.first?.title ?? "NotFound"
print(directoryObjectTitle)
}
To get the next page of search results, call the fetchNextPage() page method, which returns a deferred result Page:
firstPage?.fetchNextPage().sink{ nextPage in
let directoryObject = nextPage?.items?.first
}
Displaying results on the map
The coordinates of all found objects are returned in the itemMarkerInfos
field of the SearchResult as a list of ItemMarkerInfo elements. The list may contain no more than 15000 elements.
To display markers for all found objects on the map:
- Prepare a list of Marker objects. To set the marker position (the
position
parameter), use the coordinates from the ItemMarkerInfo.geoPoint field. - Add the prepared set of markers to the map using the
addObjects
method of the MapObjectManager. For more details, see the guide Adding multiple objects to the map.
func displaySearchResultMarkers(map: Map, searchResult: SearchResult, sdk: DGis.Container) {
// Retrieve the list of markers from the search results
let cancellable = searchResult.itemMarkerInfos.sink { markerInfos in
guard let markerInfos = markerInfos else { return }
do {
// Create an object manager to add markers to the map
let mapObjectManager = MapObjectManager(map: map)
// Prepare the list of markers
let markers = try markerInfos.compactMap { itemMarkerInfo -> Marker? in
let position = itemMarkerInfo.geoPoint
let icon = try sdk.imageFactory.make(image: UIImage(systemName: "mappin.circle.fill")!)
let options = MarkerOptions(
position: position,
icon: icon
)
return try Marker(options: options)
}
// Add the markers to the map
mapObjectManager.addObjects(objects: markers)
} catch {
print("Error creating markers: \(error.localizedDescription)")
}
} failure: { error in
print("Error getting markers: \(error.localizedDescription)")
}
}
Object data structure
Search results from the directory are presented as a list of DirectoryObject objects with sets of properties. Depending on the object type, some properties may not have values.
Important
Access to certain information about objects is only available with additional key configuration for an extra fee: see the field descriptions of DirectoryObject, Address, and ItemMarkerInfo objects. Contact 2GIS support service to update your access key settings.
-
Main properties for object classification:
- Object type (
types
) from ObjectType. One object can belong to several types (for example, the Museum of the Future in Dubai is both a museum and a architectural sight). In this case, all types will be listed, with the first element being the main object type. - Object name (
title
) depending on its type: organization name, landmark, or geographic object. For residential buildings without a name - the address. - Object subtype (
subtitle
) to specify the classification. For example, a coffee shop as a subtype of an organization or a residential building as a subtype of a building. - Object description (
description
). - Categories that the object belongs to (
rubricIds
). - Organization identifier in the directory and information about it (
orgInfo
). For companies with multiple branches - information about the head organization. - (Data on demand) Grouping of objects of different types in a single directory card (
group
). See more about grouping below.
- Object type (
-
Unique object identifier in the directory (
id
). For companies with multiple branches - the identifier of the particular branch. -
Geographic properties:
- Coordinates for placing a marker on the map (
markerPosition
). - Full address of the object (
address
). Some address components are available only on demand: see the Address object description. - (Data on demand) Information about the building floor where the object is located (
levelId
andbuildingLevels
). Relevant for companies located on a specific floor of a multi-story building. - (Data on demand) Information about entrances to the object (
entrances
) with coordinates and other data. Relevant not only for companies and buildings, but also for other objects with physically designated entrances (for example, parks). - (Data on demand) Additional information to clarify the address (
titleAddition
). For example, entrance number or apartment number.
- Coordinates for placing a marker on the map (
-
Working hours:
- Offset of the object local time from UTC in the timestamp form (
timeZoneOffset
). For example,03:00:00
for the UTC+3 timezone. - Working hours (
openingHours
) as a list of time intervals or a round-the-clock flag. Relevant for companies. - Current work status (
workStatus
).
- Offset of the object local time from UTC in the timestamp form (
-
Other data:
- (Data on demand) Information about the trade license of the organization (
tradeLicense
). - Contact information for the organization (
contactInfos
): phone number, e-mail address, website and social network links, and others. - Object rating based on user reviews (
reviews
). - Additional parking properties (
parkingInfo
). - Additional charging station properties (
chargingStation
). - Building information (
buildingInfo
).
- (Data on demand) Information about the trade license of the organization (
Object grouping
In the directory, some geographical objects can be represented as a group of objects of different types. For example, a courthouse is both a standalone building and an organization within that building, meaning two different DirectoryObject instances with characteristics of the building and the organization, respectively. Since these DirectoryObject
instances belong to the same geographical object, their data structures contain references to each other.
Information about linked objects is stored in the group
field as a list of GroupItem elements. Information about each linked object contains its type and identifier (DgisObjectId), which you can later use to access the object.
Access to data in the
group
field is only available with additional key configuration for an extra fee. Contact 2GIS support service.
Example of the group
field populated with one linked object:
group: [
GroupItem(
id: DgisObjectId(objectId: 70030076538159915, entranceId: 0),
type: .attraction
)
]
Examples
Below are examples of DirectoryObject for different types of directory objects.
-
Organization branch:
DirectoryObject
// Object type - organization branch types: [.branch], // Object name title: "Starbucks", titleAddition: nil, // Organization subtype - coffee shop subtitle: "Coffee shop", // Object ID (particular organization branch) id: DgisObjectId(objectId: 70000001006332208, entranceId: 0), // Coordinates of the marker to place on the map markerPosition: GeoPointWithElevation( latitude: Latitude(value: 25.21653), longitude: Longitude(value: 55.252752), elevation: Elevation(value: 0.0) ), // Organization address - 171, Jumeirah road, Dubai address: Address( drillDown: [ AddressAdmDiv(type: .country, name: "UAE"), AddressAdmDiv(type: .region, name: "Dubai Emirate"), AddressAdmDiv(type: .districtArea, name: "Dubai Municipality"), AddressAdmDiv(type: .city, name: "Dubai"), AddressAdmDiv(type: .division, name: "Jumeirah"), AddressAdmDiv(type: .district, name: "Jumeirah 1") ], components: [ AddressComponent(AddressStreet(street: "Jumeirah road", number: "171", fiasCode: nil)) ], buildingName: "Mercato Mall", buildingId: BuildingId(value: 13933647002354225), postCode: nil, buildingCode: nil, fiasCode: nil, addressComment: "G Floor, Shop VS1" ), // Other attributes: served food, payment types, service languages, and more attributes: [ Attribute(tag: "food_service_avg_price", value: "Average bill 25 AED"), Attribute(tag: "food_service_details_food_breakfast", value: "Breakfast menu"), Attribute(tag: "food_service_details_food_kids_menu", value: "Kids menu"), Attribute(tag: "food_service_capacity", value: "Seating capacity 90 people"), Attribute(tag: "covid_homedelivery", value: "Delivery"), Attribute(tag: "daily_services_wifi", value: "Wi-Fi"), Attribute(tag: "general_payment_type_card", value: "Card payment"), Attribute(tag: "general_payment_type_cash", value: "Cash payment"), Attribute(tag: "service_language_english", value: "English"), Attribute(tag: "service_language_hindi", value: "Hindi"), Attribute(tag: "service_language_tagalog", value: "Tagalog"), Attribute(tag: "accessible_entrance_accessible_entrance", value: "Wheelchair Accessible") ], contextAttributes: [], // Local timezone - UTC+4 timeZoneOffset: 4 * 3600, // The branch is open every day from 8:00 to 23:00 openingHours: OpeningHours( weekOpeningHours: [ [WeekTimeInterval( startTime: WeekTime(weekDay: .monday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .monday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .tuesday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .tuesday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .wednesday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .wednesday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .thursday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .thursday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .friday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .friday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .saturday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .saturday, time: DayTime(hours: 23, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .sunday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .sunday, time: DayTime(hours: 23, minutes: 0)) )] ], isOpen24x7: false ), // Ways to contact the organization contactInfos: [ ContactInfo(type: .website, displayText: "starbucks.com", value: "http://starbucks.com", comment: nil), ContactInfo(type: .twitter, displayText: "https://twitter.com/starbucks", value: "https://twitter.com/starbucks", comment: nil), ContactInfo(type: .facebook, displayText: "https://facebook.com/StarbucksMiddleEast", value: "https://facebook.com/StarbucksMiddleEast", comment: nil), ContactInfo(type: .instagram, displayText: "https://instagram.com/starbucksmiddleeast", value: "https://instagram.com/starbucksmiddleeast", comment: nil), ContactInfo(type: .linkedin, displayText: "https://linkedin.com/company/starbucks", value: "https://linkedin.com/company/starbucks", comment: nil), ContactInfo(type: .pinterest, displayText: "https://pinterest.com/starbucks", value: "https://pinterest.com/starbucks", comment: nil), ContactInfo(type: .youtube, displayText: "https://youtube.com/user/Starbucks", value: "https://youtube.com/user/Starbucks", comment: nil), ContactInfo(type: .pobox, displayText: "P.O.Box 1277", value: "1277", comment: nil), ContactInfo(type: .phone, displayText: "+971 4 3153636", value: "+97143153636", comment: nil), ContactInfo(type: .email, displayText: "sbk.mercato-uae@alshaya.com", value: "sbk.mercato-uae@alshaya.com", comment: nil) ], // Rating is 4.0 based on 25 reviews reviews: Reviews(rating: 4.0, count: 25), parkingInfo: nil, // The branch is currently open and will be until 23:00 workStatus: WorkStatus(isOpen: true, description: "Open until 23:00"), // The branch is located on the G floor of the building levelId: LevelId(value: 70030076166076253), buildingLevels: nil, // The organization has three entrances entrances: [ EntranceInfo( id: DgisObjectId(objectId: 70000001006332208, entranceId: 139336470023548743), buildingNumber: nil, porchName: nil, porchNumber: nil, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.216795), longitude: Longitude(value: 55.25238)), GeoPoint(latitude: Latitude(value: 25.216828), longitude: Longitude(value: 55.253393)), GeoPoint(latitude: Latitude(value: 25.215802), longitude: Longitude(value: 55.252601)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.216846), longitude: Longitude(value: 55.252298)), GeoPoint(latitude: Latitude(value: 25.216795), longitude: Longitude(value: 55.25238)) ], [ GeoPoint(latitude: Latitude(value: 25.216902), longitude: Longitude(value: 55.253455)), GeoPoint(latitude: Latitude(value: 25.216828), longitude: Longitude(value: 55.253393)) ], [ GeoPoint(latitude: Latitude(value: 25.215737), longitude: Longitude(value: 55.252301)), GeoPoint(latitude: Latitude(value: 25.215802), longitude: Longitude(value: 55.252601)) ] ] ) ) ], chargingStation: nil, // The object belongs to one category rubricIds: [RubricId(value: 162)], // Information about the head organization and the total count of branches orgInfo: OrgInfo(branchCount: 310, id: OrgId(value: 70000001033047305), name: "Starbucks, coffee shop"), group: []
-
Residential building:
DirectoryObject
// Object type - building types: [.building], // Object name title: "DT-1 Ellington Tower", titleAddition: nil, // Object subtype - residential building subtitle: "Residential building", // Object ID id: DgisObjectId(objectId: 70030076167127391, entranceId: 0), // Coordinates of the marker to place on the map markerPosition: GeoPointWithElevation( latitude: Latitude(value: 25.191471), longitude: Longitude(value: 55.269194), elevation: Elevation(value: 9.0) ), // Organization address - 7, Burj Khalifa street, Dubai address: Address( drillDown: [ AddressAdmDiv(type: .country, name: "UAE"), AddressAdmDiv(type: .region, name: "Dubai Emirate"), AddressAdmDiv(type: .districtArea, name: "Dubai Municipality"), AddressAdmDiv(type: .city, name: "Dubai"), AddressAdmDiv(type: .division, name: "Za'abeel"), AddressAdmDiv(type: .district, name: "Burj Khalifa/Downtown Dubai") ], components: [ AddressComponent(AddressStreet(street: "Burj Khalifa street", number: "7", fiasCode: nil)) ], buildingName: nil, buildingId: BuildingId(value: 70030076167127391), postCode: nil, buildingCode: nil, fiasCode: nil, addressComment: nil ), attributes: [], contextAttributes: [], timeZoneOffset: nil, openingHours: nil, contactInfos: [], reviews: nil, parkingInfo: nil, workStatus: WorkStatus(isOpen: false, description: ""), levelId: nil, buildingLevels: nil, // The building has four entrances entrances: [ EntranceInfo( id: DgisObjectId(objectId: 70030076167127391, entranceId: 70030076324754702), buildingNumber: nil, porchName: nil, porchNumber: nil, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.19140378756845), longitude: Longitude(value: 55.26913163325181)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.191347), longitude: Longitude(value: 55.269055)), GeoPoint(latitude: Latitude(value: 25.191404), longitude: Longitude(value: 55.269132)) ] ] ) ), EntranceInfo( id: DgisObjectId(objectId: 70030076167127391, entranceId: 7003007632475404), buildingNumber: nil, porchName: nil, porchNumber: nil, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.19158093529474), longitude: Longitude(value: 55.2695519032598)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.191915), longitude: Longitude(value: 55.269672)), GeoPoint(latitude: Latitude(value: 25.191858), longitude: Longitude(value: 55.269595)) ] ] ) ), EntranceInfo( id: DgisObjectId(objectId: 70030076167127391, entranceId: 7003007632475407), buildingNumber: nil, porchName: nil, porchNumber: nil, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.19173213009156), longitude: Longitude(value: 55.26907392050657)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.191789), longitude: Longitude(value: 55.269785)), GeoPoint(latitude: Latitude(value: 25.191732), longitude: Longitude(value: 55.269701)) ] ] ) ), EntranceInfo( id: DgisObjectId(objectId: 70030076167127391, entranceId: 70030076269579911), buildingNumber: nil, porchName: "Entrance 1", porchNumber: 1, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.191795238515603), longitude: Longitude(value: 55.26951389492054)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.191852), longitude: Longitude(value: 55.269728)), GeoPoint(latitude: Latitude(value: 25.191795), longitude: Longitude(value: 55.269651)) ] ] ) ) ], chargingStation: nil, rubricIds: [], orgInfo: nil, group: []
-
Street:
DirectoryObject
// Object type - street types: [.street], // Object name title: "9 street", titleAddition: nil, // Object subtype - street subtitle: "Street", // Object ID id: DgisObjectId(objectId: 13933750081556578, entranceId: 0), // Coordinates of the marker to place on the map markerPosition: GeoPointWithElevation( latitude: Latitude(value: 25.166536), longitude: Longitude(value: 55.261352), elevation: Elevation(value: 0.0) ), // Organization address - Dubai, Al Qouz 1 address: Address( drillDown: [ AddressAdmDiv(type: .country, name: "UAE"), AddressAdmDiv(type: .region, name: "Dubai Emirate"), AddressAdmDiv(type: .districtArea, name: "Dubai Municipality"), AddressAdmDiv(type: .city, name: "Dubai"), AddressAdmDiv(type: .district, name: "Al Qouz 1") ], components: [], buildingName: nil, buildingId: nil, postCode: nil, buildingCode: nil, fiasCode: nil, addressComment: nil ), attributes: [], contextAttributes: [], timeZoneOffset: nil, openingHours: nil, contactInfos: [], reviews: nil, parkingInfo: nil, workStatus: WorkStatus(isOpen: false, description: ""), levelId: nil, buildingLevels: nil, entrances: [], chargingStation: nil, rubricIds: [], orgInfo: nil, group: []
-
Polygon object (park):
DirectoryObject
// Object type - organization branch types: [.branch], // Object name title: "Al Nahda Pond Park", titleAddition: nil, // Object subtype - park subtitle: "Parks", // Object ID id: DgisObjectId(objectId: 70000001067100914, entranceId: 0), // Coordinates of the marker to place on the map markerPosition: GeoPointWithElevation( latitude: Latitude(value: 25.290345), longitude: Longitude(value: 55.380582), elevation: Elevation(value: 3.0) ), // Organization address - 4, 22 street, Al Nahda 2, Dubai address: Address( drillDown: [ AddressAdmDiv(type: .country, name: "UAE"), AddressAdmDiv(type: .region, name: "Dubai Emirate"), AddressAdmDiv(type: .districtArea, name: "Dubai Municipality"), AddressAdmDiv(type: .city, name: "Dubai"), AddressAdmDiv(type: .division, name: "Deira"), AddressAdmDiv(type: .district, name: "Al Nahda 2") ], components: [ AddressComponent(AddressStreet(street: "22 street", number: "4", fiasCode: nil)) ], buildingName: nil, buildingId: BuildingId(value: 13933647002428254), postCode: nil, buildingCode: nil, fiasCode: nil, addressComment: nil ), // Other attributes: entrance fee and available facilities attributes: [ Attribute(tag: "summer_entrance_parks_free", value: "Free Entrance"), Attribute(tag: "summer_optional_parks_playground", value: "Playground"), Attribute(tag: "summer_optional_parks_jogging_track", value: "Jogging Track"), Attribute(tag: "summer_optional_parks_sports_facilities", value: "Sports Facilities") ], contextAttributes: [], // Local timezone - UTC+4 timeZoneOffset: 4 * 3600, // The object is open every day from 8:00 to 1:00 openingHours: OpeningHours( weekOpeningHours: [ [WeekTimeInterval( startTime: WeekTime(weekDay: .monday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .monday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .tuesday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .tuesday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .wednesday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .wednesday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .thursday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .thursday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .friday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .friday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .saturday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .saturday, time: DayTime(hours: 1, minutes: 0)) )], [WeekTimeInterval( startTime: WeekTime(weekDay: .sunday, time: DayTime(hours: 8, minutes: 0)), finishTime: WeekTime(weekDay: .sunday, time: DayTime(hours: 1, minutes: 0)) )] ], isOpen24x7: false ), contactInfos: [], reviews: nil, parkingInfo: nil, // The branch is currently open and will be until 01:00 workStatus: WorkStatus(isOpen: true, description: "Open until 01:00"), levelId: nil, buildingLevels: nil, // The organization has one entrance entrances: [ EntranceInfo( id: DgisObjectId(objectId: 70000001067100914, entranceId: 70030076171889579), buildingNumber: nil, porchName: nil, porchNumber: nil, apartmentRanges: [], geometry: EntranceGeometry( entrancePoints: [ GeoPoint(latitude: Latitude(value: 25.290353695590525), longitude: Longitude(value: 55.38058040032387)) ], entrancePolylines: [ [ GeoPoint(latitude: Latitude(value: 25.290443), longitude: Longitude(value: 55.380568)), GeoPoint(latitude: Latitude(value: 25.290354), longitude: Longitude(value: 55.38058)) ] ] ) ) ], chargingStation: nil, // The object belongs to one category rubricIds: [RubricId(value: 168)], // Information about the head organization, which is equal to the current branch orgInfo: OrgInfo(branchCount: 1, id: OrgId(value: 70000001067100913), name: "Al Nahda Pond Park"), group: []
Search suggestions
You can build suggestions when text searching for objects (see Suggest API). To do this, create a SuggestQuery object using SuggestQueryBuilder and pass it to the suggest() method:
let query = SuggestQueryBuilder.fromQueryText(queryText: "pizz").setLimit(limit: 10).build()
searchManager.suggest(query: query).sink{ suggestResult in
// Get the first suggestion from the list
let firstSuggestTitle = suggestResult.suggests.first ?? ""
print(firstSuggestTitle)
}
The method returns a deferred SuggestResult which contains a list of suggestions (Suggest).
Search history
You can work with the search history using the SearchHistory class.
The search history can contain two types of items: directory objects (DirectoryObject) and search queries (SearchQueryWithInfo).
Adding items to search history
You can add items to the search history as SearchHistoryItem objects, either one at a time or as a list. The order of items in the list will be preserved when added to the history.
-
Create a SearchHistoryItem object and pass one of the following objects depending on the type of item being added:
-
For a search query: SearchQueryWithInfo with the desired search query specified in the
searchQuery
parameter. Additionally,SearchQueryWithInfo
can include a title and subtitle, which will be displayed in the search history results.// Create a SearchQueryWithInfo object let searchQueryWithInfo = SearchQueryWithInfo( searchQuery: searchQuery, // prepared search query title: "Nearby Cafes", subtitle: "Restaurants and cafes nearby" ) let searchHistoryItem = SearchHistoryItem.searchQuery(searchQueryWithInfo)
-
For a directory object: DirectoryObject.
let searchHistoryItem = SearchHistoryItem.directoryObject(directoryObject)
-
-
Create a SearchHistory object:
let searchHistory = SearchHistory(context: context)
-
Add items to the search history one at a time or as a list using the
addItem()
oraddItems()
methods of the SearchHistory object, respectively:-
Add a single item:
searchHistory.addItem(item: searchHistoryItem)
-
Add a list of items:
searchHistory.addItems(items: searchHistoryItemsList)
-
If an item already exists in the search history, the older duplicate will be removed.
Displaying search history
To display the search history page with a list of items, create a SearchHistoryPage object and pass it to the items() method. Additionally, you can configure the following parameters:
- Limit the number of items per page (
limit
parameter). The default value is 100. - Set an offset from the beginning of the list (
offset
parameter): how many elements from the beginning to skip. The default value is 0 (no offset, the list is displayed from the beginning). - Filter the list by item type (
filter
parameter). Available filters are listed in SearchHistoryFilter. For example, to show only search queries in the history, use theSEARCH_QUERY
value. By default, no filtering is applied.
// Create a SearchHistory object
let searchHistory = SearchHistory(context: context)
// Create a history page with a limit of 10 items and an offset of 0
let page = SearchHistoryPage(
limit: 10, // Maximum 10 items per page
offset: 0, // Offset 0 (start of the list)
filter: [] // No filters
)
// Retrieve the items on the history page
searchHistory.items(page: page).sink { result in
result.items.forEach { item in
// Log each history item
print("History item: \(item)")
}
} failure: { error in
print("Failed to retrieve page from search history: \(error)")
}
The items on the page are sorted by the time they were added to the history (newest to oldest).
Clearing search history
To remove specific items from the search history:
-
To remove a single item, use the
removeItem()
method of the SearchHistory object and pass the required SearchHistoryItem. For more details onSearchHistoryItem
contents, see the Add items to search history instruction.searchHistory.removeItem(item: searchHistoryItem)
-
To remove multiple items, use the
removeItems()
method of the SearchHistory object and pass a list of the required SearchHistoryItem objects. For more details onSearchHistoryItem
contents, see the Add items to search history instruction.searchHistory.removeItems(items: searchHistoryItemsList)
To completely clear the search history, use the clear()
method of the SearchHistory object:
searchHistory.clear()
Subscription to history changes
To track changes in the search history (adding and removing items), you can subscribe to the onHistoryChanged channel:
let searchHistory = SearchHistory(context: context)
searchHistory.onHistoryChanged.sink { changeType in
switch changeType {
case .add:
print("An item was added to the history")
case .remove:
print("An item was removed from the history")
@unknown default:
print("Unknown history change")
}
}
Information about entrances in the directory
You can search for addresses in the directory with the exact apartment or entrance number.
DgisObjectId contains two identifiers:
- objectId - stable numeric identifier of the object.
- entranceId - stable numeric identifier of the object entrance.
If the entranceId is non-zero, then the search result is not a building but a specific entrance.
If you need to draw a marker on a specific entrance or get its coordinates to calculate a route, do not use markerPosition. This property contains the position related to the marker of the building. To get the entrance position, use the information from entrances:
func getMarkerPosition(directoryObject: DirectoryObject) -> GeoPoint? {
guard let entranceId = directoryObject.id?.entranceId,
let info = directoryObject.entrances.first(where: { $0.id.entranceId == entranceId }),
let entrancePoint = info.geometry?.entrancePoints.first else {
return directoryObject.markerPosition?.point
}
return entrancePoint
}