import UIKit import ArcGIS
class ViewController: UIViewController ,UIPickerViewDataSource,UIPickerViewDelegate{
func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { Category.all.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { Category.all[row].title } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { findPlaces(forCategory: Category.all[row]) } @IBOutlet weak var mapView: AGSMapView! @IBOutlet weak var categoryPicker: UIPickerView! private let placesOverlay = AGSGraphicsOverlay() private let locatorTask = AGSLocatorTask(url: .locator) private var currentSearch: AGSCancelable? private var isNavigatingObservation: NSKeyValueObservation? private var visibleAreaObservation: NSKeyValueObservation? override func viewDidLoad() { super.viewDidLoad() initialMap() observeChangesInMapViewIsNavigating() observeChangesInMapViewVisibleArea() } private func observeChangesInMapViewIsNavigating() { isNavigatingObservation = mapView.observe(\.isNavigating) { [weak self] (mapView, _) in guard !mapView.isNavigating else { return } self?.findPlacesForCategoryPickerSelection() } } private func observeChangesInMapViewVisibleArea() { visibleAreaObservation = mapView.observe(\.visibleArea) { [weak self] (mapView, _) in guard let self = self else { return } self.findPlacesForCategoryPickerSelection() self.visibleAreaObservation = nil } } func initialMap(){
mapView.map = AGSMap(basemapType: .navigationVector, latitude: 34.09042, longitude: -118.71511, levelOfDetail: 10) mapView.graphicsOverlays.add(placesOverlay) mapView.touchDelegate = self } func addPlacesGraphics(_ results: [AGSGeocodeResult],for category: Category){ let symbol: AGSSimpleMarkerSymbol = { let placeSymbol = AGSSimpleMarkerSymbol(style: .circle, color: category.color, size: 10.0) placeSymbol.outline = AGSSimpleLineSymbol(style: .solid, color: .white, width: 2) return placeSymbol }() let places = results.map { (result) in AGSGraphic(geometry: result.displayLocation, symbol: symbol, attributes: result.attributes) } placesOverlay.graphics.addObjects(from: places) } func clearPlacesGraphics(){ placesOverlay.graphics.removeAllObjects() } func showCallout(for graphic: AGSGraphic){ mapView.callout.title = graphic.attributes[String.placeName] as? String ?? "Unknown" mapView.callout.detail = graphic.attributes[String.placeAddress] as? String ?? "no address provided" mapView.callout.show(for: graphic, tapLocation: graphic.geometry as? AGSPoint, animated: true) } func hideCallout(){ if mapView != nil { mapView.callout.dismiss() } } func findPlaces(forCategory category: Category){ guard let visibleArea = mapView.visibleArea else {return} hideCallout() clearPlacesGraphics() currentSearch?.cancel() let paramters: AGSGeocodeParameters = { let geocodeParameters = AGSGeocodeParameters() geocodeParameters.maxResults = 25 geocodeParameters.resultAttributeNames.append(contentsOf: [. placeAddress,.placeName]) geocodeParameters.preferredSearchLocation = visibleArea.extent.center geocodeParameters.categories = [category.title] return geocodeParameters }() currentSearch = locatorTask.geocode(withSearchText: "", parameters: paramters, completion: { [weak self] (result, error) in guard let self = self else {return} guard error == nil else{ print("Geocode error: ",error!.localizedDescription) return } guard let result = result,result.count > 0 else{ print("No places found for category ",category.title) return } self.addPlacesGraphics(result, for: category) }) } private func findPlacesForCategoryPickerSelection(){ DispatchQueue.main.async { [weak self] in guard let self = self else {return} let categoryIndex = self.categoryPicker.selectedRow(inComponent: 0) guard categoryIndex < Category.all.count else {return} let category = Category.all[categoryIndex] self.findPlaces(forCategory: category) } } }
extension ViewController: AGSGeoViewTouchDelegate{ func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { hideCallout() mapView.identify(placesOverlay, screenPoint: screenPoint, tolerance: 10, returnPopupsOnly: false, maximumResults: 1) { [weak self](result) in guard let self = self else { return } if let error = result.error{ print(error) return } else if let graphic = result.graphics.first{ self.showCallout(for: graphic) } } } }
|