This is my first attempt with the Runtime SDK for iOS with Swift (after finding the Qt Runtime SDK to be too buggy) and I have some questions regarding the workflow for creating programmatic popups. All the code samples I have seen have used AGOL web maps rather than feature services directly. So far, I just have a basic map with a map service and 2 feature layers that I need to make pop ups for. I have set up the AGSPopupInfo's for each feature layer and am not sure what the rest of the workflow should look like.
My best guess is to call the queryFeatures() method from each feature layer and pass in a geometry from the map touch delegate. From here, I am stuck as I do not know how to handle the query delegate and more specifically passing the operation returned from the query to the handler since it is outside the scope where the query operation is performed. I think I should also be using the AGSPopupsContainer as well. Is there a better or more appropriate workflow to accomplish this?
Does anyone have any code samples for how you have done programmatic popups for feature service layers (not AGOL web maps)? This is the code I have so far but I am struggling:
import UIKit
import ArcGIS
let kBasemapLayerName = "Basemap Tiled Layer"
var isAdmin = false
let sightingFields = ["Visual_Cue", "Tree_Stress", "Knowledge_Level", "EAB_Found_On", "Comments", "Site_Description", "Latitude", "Longitude", "Site_Address", "Inspector_Name", "Email"]
let countyFields = ["CTY_NAME", "QUARANTINED"]
// MARK: reference feature layers
let countiesURL = NSURL(string: "http://services.arcgis.com/g2UdLvZr5lOrmlXl/arcgis/rest/services/EAB_FS/FeatureServer/1")
let counties = AGSFeatureLayer(URL: countiesURL, mode: .Snapshot)
let sightingURL = NSURL(string: "http://services.arcgis.com/g2UdLvZr5lOrmlXl/arcgis/rest/services/EAB_FS/FeatureServer/0")
let sightings = AGSFeatureLayer(URL: sightingURL, mode: .OnDemand)
class FirstViewController: UIViewController, AGSMapViewLayerDelegate, AGSCalloutDelegate, AGSMapViewTouchDelegate, AGSPopupsContainerDelegate {
@IBOutlet weak var mapView: AGSMapView!
var popupVC:AGSPopupsContainerViewController!
override func viewDidLoad() {
super.viewDidLoad()
// MARK: set up map with default basemaps and feature layers
let streetsURL = "http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer"
let tiledLayer = AGSTiledMapServiceLayer(URL: NSURL(string: streetsURL))
self.mapView.addMapLayer(tiledLayer, withName: kBasemapLayerName)
// mapview layer delegate
self.mapView.layerDelegate = self
self.mapView.touchDelegate = self
// MDA EAB service
let mneabURL = NSURL(string: "http://gis.mda.state.mn.us/arcgis/rest/services/MN_Agriculture_EAB_Detection/MapServer")
let eabDynMS = AGSDynamicMapServiceLayer(URL: mneabURL)
self.mapView.addMapLayer(eabDynMS, withName: "MDA EAB Service")
// make counties transparent
counties.opacity = 0.5
self.mapView.addMapLayer(counties, withName: "Counties")
self.mapView.addMapLayer(sightings, withName: "Sightings")
//MARK: Feature Layer popups for sightings and counties
// sightings
let sightingPopupInfo = AGSPopupInfo(forFeatureLayer: sightings)
sightingPopupInfo.showAttachments = true
sightingPopupInfo.fieldInfos = sightingFields
// counties
let countyPopupInfo = AGSPopupInfo(forFeatureLayer: counties)
countyPopupInfo.fieldInfos = countyFields
}
// MARK: query features from touch delegate for mapview
func mapView(mapView: AGSMapView!, didClickAtPoint screen: CGPoint, mapPoint mappoint: AGSPoint!, features: [NSObject : AnyObject]!) {
let geometryEngine = AGSGeometryEngine.defaultGeometryEngine()
let buffer = geometryEngine.bufferGeometry(mappoint, byDistance:(10 * mapView.resolution))
// query for sightings
var querySightings = AGSQuery()
querySightings.geometry = buffer
querySightings.outFields = sightingFields
sightings.queryFeatures(querySightings)
// query for counties
var queryCounties = AGSQuery()
queryCounties.geometry = buffer
queryCounties.outFields = countyFields
var countyQueryOp = counties.queryFeatureCount(queryCounties)
}
// I am not sure how to do handle the query results and display popups from resulting features
// MARK: handle query delegates (not sure how to pass operations from outside touch delegate scope)
func featureLayer(featureLayer: AGSFeatureLayer!, op: NSOperation, didQueryFeaturesWithFeatureSet: AGSFeatureSet?) {
}
// MARK: get user's location
func mapViewDidLoad(mapView: AGSMapView!) {
mapView.locationDisplay.startDataSource()
mapView.locationDisplay.autoPanMode = .Default
mapView.locationDisplay.wanderExtentFactor = 0.75
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: switch basemaps
@IBAction func basemapChanged(sender: UISegmentedControl) {
var basemapURL: NSURL
switch sender.selectedSegmentIndex {
case 0: //streets
basemapURL = NSURL(string: "http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer")!
case 1: // aerial
basemapURL = NSURL(string: "http://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer")!
default: //streets
basemapURL = NSURL(string: "http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer")!
}
self.mapView.removeMapLayerWithName(kBasemapLayerName)
let newBasemapLayer = AGSTiledMapServiceLayer(URL: basemapURL)
self.mapView.insertMapLayer(newBasemapLayer, withName: kBasemapLayerName, atIndex: 0)
}
}
Solved! Go to Solution.
The features are already provided in the mapView:didClickAtPoint:mapPoint:features: method on the touch delegate. So you don't need a query. The features parameter is a dictionary of feature layer names as keys and the features in those layers as the values.
Simply create an AGSPopupInfo object using popupInfoForFeatureLayer: initializer. And use that to create AGSPopups and eventually an AGSPopupsContainerViewController to display them all.
The features are already provided in the mapView:didClickAtPoint:mapPoint:features: method on the touch delegate. So you don't need a query. The features parameter is a dictionary of feature layer names as keys and the features in those layers as the values.
Simply create an AGSPopupInfo object using popupInfoForFeatureLayer: initializer. And use that to create AGSPopups and eventually an AGSPopupsContainerViewController to display them all.
Thank you very much. I was able to figure this out due to your suggestions.
Is it possible to create our own view to display AGSPopupInfo data instead of using AGSPopupsContainerViewController. I cannot customize it, therefore i need a custom display, Please do suggest a way how can i handle it to show in custom view. I m using your offline editing sample in swift.
Regards.
Thank you.