Use an online service to find the address for a tapped point.
Use case
You might use a geocoder to find a customer's delivery address based on the location returned by their device's GPS.
How to use the sample
Tap the map to see the nearest address displayed in a callout.
How it works
Create an AGSLocatorTask object using a URL to a geocoder service.
Create an instance of AGSReverseGeocodeParameters and set AGSReverseGeocodeParameters.maxResults to 1.
Pass AGSReverseGeocodeParameters into AGSLocatorTask.reverseGeocode(withLocation:parameters:completion:) and get the matching results from the AGSGeocodeResult.
Show the results using an AGSPictureMarkerSymbol and add the symbol to an AGSGraphic in the AGSGraphicsOverlay.
Relevant API
AGSGeocodeParameters
AGSLocatorTask
AGSReverseGeocodeParameters
Additional information
This sample uses the World Geocoding Service. For more information, see Geocoding service from ArcGIS for Developers.
Tags
address, geocode, locate, reverse geocode, search
Sample Code
ReverseGeocodeViewController.swift
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2016 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.import UIKit
import ArcGIS
classReverseGeocodeViewController: UIViewController, AGSGeoViewTouchDelegate{
@IBOutletweakvar mapView: AGSMapView! {
didSet {
// Create an instance of a map with ESRI topographic basemap. mapView.map =AGSMap(basemapStyle: .arcGISTopographic)
mapView.touchDelegate =self// Add the graphics overlay. mapView.graphicsOverlays.add(self.graphicsOverlay)
// Zoom to a specific extent. mapView.setViewpoint(AGSViewpoint(center: AGSPoint(x: -117.195, y: 34.058, spatialReference: .wgs84()), scale: 5e4))
}
}
privatelet locatorTask =AGSLocatorTask(url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!)
privatevar graphicsOverlay =AGSGraphicsOverlay()
privatevar cancelable: AGSCancelable!
overridefuncviewDidLoad() {
super.viewDidLoad()
// Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as!SourceCodeBarButtonItem).filenames = ["ReverseGeocodeViewController"]
}
privatefuncreverseGeocode(_point: AGSPoint) {
// Cancel previous request.ifself.cancelable !=nil {
self.cancelable.cancel()
}
// Hide the callout.self.mapView.callout.dismiss()
// Remove already existing graphics.self.graphicsOverlay.graphics.removeAllObjects()
// Normalize point.let normalizedPoint =AGSGeometryEngine.normalizeCentralMeridian(of: point) as!AGSPointlet graphic =self.graphicForPoint(normalizedPoint)
self.graphicsOverlay.graphics.add(graphic)
// Initialize parameters.let reverseGeocodeParameters =AGSReverseGeocodeParameters()
reverseGeocodeParameters.maxResults =1// Reverse geocode.self.cancelable =self.locatorTask.reverseGeocode(withLocation: normalizedPoint, parameters: reverseGeocodeParameters) { [weakself] (results: [AGSGeocodeResult]?, error: Error?) iniflet error = error {
// Present user canceled error.if (error asNSError).code !=NSUserCancelledError {
self?.presentAlert(error: error)
}
} elseiflet result = results?.first {
graphic.attributes.addEntries(from: result.attributes!)
self?.showCalloutForGraphic(graphic, tapLocation: normalizedPoint)
return } else {
self?.presentAlert(message: "No address found")
}
self?.graphicsOverlay.graphics.remove(graphic)
}
}
/// Method returns a graphic object for the specified point and attributes.privatefuncgraphicForPoint(_point: AGSPoint) -> AGSGraphic {
let markerImage =UIImage(named: "RedMarker")!let symbol =AGSPictureMarkerSymbol(image: markerImage)
symbol.leaderOffsetY = markerImage.size.height /2 symbol.offsetY = markerImage.size.height /2let graphic =AGSGraphic(geometry: point, symbol: symbol, attributes: [String: AnyObject]())
return graphic
}
/// Show callout for the graphic.privatefuncshowCalloutForGraphic(_graphic: AGSGraphic, tapLocation: AGSPoint) {
// Get the attributes from the graphic and populates the title and detail for the callout.let cityString = graphic.attributes["City"] as?String??""let addressString = graphic.attributes["Address"] as?String??""let stateString = graphic.attributes["State"] as?String??""self.mapView.callout.title = addressString
self.mapView.callout.detail ="\(cityString)\(stateString)"self.mapView.callout.isAccessoryButtonHidden =trueself.mapView.callout.show(for: graphic, tapLocation: tapLocation, animated: true)
}
// MARK: - AGSGeoViewTouchDelegatefuncgeoView(_geoView: AGSGeoView, didTapAtScreenPointscreenPoint: CGPoint, mapPoint: AGSPoint) {
self.reverseGeocode(mapPoint)
}
}