iosswiftnsmutablearrayarcgis-runtime

Move and/or Remove Markers in ArcGIS Graphics Layer


I'm using the ArcGIS 100.6 iOS SDK and am populating the map with markers on a Graphics Overlay Layer whose locations are stored in a database common to all users of my application. Each marker is stored in a unique record and each record contains the Latitude & Longitude of the marker. When the App is launched it reads the location of all markers in the database and adds each one to the Graphics Overlay as shown below:

let areaMarker = AGSPictureMarkerSymbol(image: UIImage(named: "CustomMarker")!)
let areaMarkerLocation = AGSPointMakeWGS84(y ?? 0.0, x ?? 0.0)
let markerIcon = AGSGraphic(geometry: areaMarkerLocation, symbol: areaMarker, attributes: >["marker": markerKey])
self.overlay.graphics.add(markerIcon)

As shown above, each marker is assigned an attribute "marker:markerKey" that is the unique database record number (key) where the marker location information is stored and serves as the marker ID.

Once the initial markers are added to the Overlay, the App "Listens" to the database for the following events:

When a marker is moved or deleted the database listener is notified and passed the record number (key) of the marker that was moved (or deleted). If the marker was moved, the record will then contain the new Latitude & Longitude information.

I have experimented with reading the graphics overlay and determined that it is a Collection contained in a NSMutable Array. I can read all attributes as follows:

let graphicsCollection = self.overlay.graphics.mutableArrayValue(forKey: "attributes")
print(graphicsCollection)

The result is:

(
        {
        marker = "-KlRW2_rba1zBrDPpxSl";
    },
{
        marker = "-Lu915xF3zQp4dIYnsP_";
    }
)

I can do the same for "geometry" and get the array of AGSPoints:

let graphicsCollection = self.overlay.graphics.mutableArrayValue(forKey: "geometry")
print(graphicsCollection)

The result is:

(
    "AGSPoint: (-117.826127, 44.781139), sr: 4326",
    "AGSPoint: (-112.056906, 33.629829), sr: 4326"
)

I have been unable to determine how to get the "index" of the attribute array (e.g. marker "-KlRW2_rba1zBrDPpxSl" above should have an index of [0]) so I can then use that "index" to access the appropriate AGSPoint and update the Latitude & Longitude or remove the marker.

Thanks in advance for the help.


Solution

  • If you want to move the marker (i.e. an AGSGraphic) you'll want to get the AGSGraphic itself and modify the geometry property. I think that by jumping to the "geometry" in your mutableArrayValue() call you're kind of shooting yourself in the foot a bit.

    I would tackle it this way:

    let searchMarker = "-KlRW2_rba1zBrDPpxSl"
    let newLocation = AGSPointMakeWGS84(40.7128, -74.0060) // NYC
    if let graphic = (overlay.graphics as? [AGSGraphic])?.first(where: { 
        ($0.attributes["marker"] as? String) == searchMarker
    }) {
        // Move the graphic
        graphic.geometry = newLocation
        // Or remove the graphic
        overlay.graphics.remove(graphic)
    }