Save AGSMapView viewpoint after user zoom/pan

1116
6
10-25-2019 12:48 AM
marius
by
New Contributor III

Hello,

I'm running into an issue when trying to save the current map viewpoint only after a user interaction.

I've implemented viewpointChangedHandler, however, that method is called also when the map is programatically setup (e.g. at start up).

To avoid saving a map position that wasn't set by the user, I'm also checking that isNavigating == true, however that doesn't seem to be enough. It seems that isNavigating might be true/false in other situations as well.

Logs from my tests:

// Loading map (with viewpoint set to 37.926438,-122.070035,0.004000,0.006430,0.000000)
18:28:37:196 isNavigating: true viewpoint: -0.000000,0.000000,160.809973,360.000000,0.000000
18:28:37:228 isNavigating: true viewpoint: 0.000052,-0.000931,160.798596,359.913489,0.000000
18:28:37:450 isNavigating: false viewpoint: 37.926438,-122.070035,0.004000,0.006430,0.000000

// Rotating map, pan, zoom
18:29:40:253 isNavigating: true viewpoint: 37.926362,-122.070321,0.002501,0.004020,79.688963
18:29:40:570 isNavigating: true viewpoint: 37.926356,-122.070335,0.002631,0.004229,83.738892
18:29:40:821 isNavigating: true viewpoint: 37.926357,-122.070380,0.002793,0.004489,97.041926
18:29:41:040 isNavigating: false viewpoint: 37.926358,-122.070381,0.002793,0.004489,97.376031
18:29:43:911 isNavigating: true viewpoint: 37.926354,-122.070384,0.002873,0.004618,97.376031

I found this thread for the old SDK notification when user moves map, that can be combined with lastChangeFromInteraction, but I can't find something similar in SDK 100.6.

What's the most reliable way to save the viewpoint after a user interaction?

Thank you,
Marius

0 Kudos
6 Replies
Nicholas-Furness
Esri Regular Contributor

We use isNavigating in the open source maps app and it works well.

maps-app-ios/MapViewController+AppPreferences.swift at de272de41a2cdcda680a1a296c6467339b63c422 · Es... 

You could prevent storing the viewpoint until the first isNavigating = false after setting the initial viewpoint.

Out of interest, are you setting the map's viewpoint with an AGSMap constructor, or setting its initialViewpoint before assigning it to the AGSMapView, or are you setting the viewpoint on the AGSMapView?

Lastly, in your second set of logs, the isNavigating = false event at 18:29:41:040 looks like it's because the user has not moved the map, even though they might still have their fingers on the map view. Is that possible? But I would expect another log entry after 18:29:43:911 where isNavigating is false again. Did you not see that, or are the logs just a subset?

0 Kudos
marius
by
New Contributor III

Thanks for this Nick.

I'll check setting an observable on isNavigating, but ignoring it until the first isNavigating = false, sounds weird...

This is a simplified layout of the maps code, all in the same class, with the self/strongSelf/etc bits removed.

// At view init time
mapView.viewpointChangedHandler = {
  if mapView.isNavigating {
    // Save changed map position
  }
}

// At map change
webMap = AGSMap(item: userMap)
// webMap = AGSMap(basemap: basemap)
if mapView.map != nil {
  let currentViewpoint = mapView.currentViewpoint(with: .centerAndScale)
  webMap.initialViewpoint = currentViewpoint
}

webMap.load() {
  mapView.map = nil
  mapView.map = webMap
}

Re the set of logs, it's a truncated representation. I've moved the map around, and those gaps were there while manipulating the map. Maybe the gaps are from when the map was moving out of inertia though. If it helps, I can record a video.

0 Kudos
MichaelDavis3
Occasional Contributor III

We use the viewpointChangedHandler to trigger a redraw of our scale bar as well as stashing the viewpoint in NSUserDefaults.  Have to go Viewpoint->JSON->NSDictionary to get it in there but it is handy way to have the last viewpoint available if the app is closed in the background, or if we destroy the map view and want to reconstitute it later.

I haven't noticed a huge issue with it triggering for non-pan/zoom activities.  It happens but doesn't really impact performance in any major way.  I guess if we were so inclined we could compare the extent of the saved viewpoint with the current viewpoint and only update if different.

0 Kudos
marius
by
New Contributor III

My problem is not performance, but the fact that during the "setup" of the viewpoint, the reported currentViewpoint goes from 0,0 to the destination viewpoint and reports some of the intermediate states... (e.g. you may end up with 10,10 as a valid value, with isNavigating set to true, however that's just a transition from 0,0 to 100,100).

0 Kudos
MichaelDavis3
Occasional Contributor III

Ahh I see - The way we avoid that is by making the assignment of viewpointChangedHandler the very last thing we do in the setup of the map.  We load the map, zoom to any previously stored viewpoint, set up basemap and base layers, reconstitute any definition queries we might have... and then set the handler.  This seems to have minimized that sort of premature activity for us.

0 Kudos
marius
by
New Contributor III

Thanks Michael. After explaining the problem in the earlier post, I thought that this might be the solution. I'll give that a try.

0 Kudos