I am creating a Dynamic map app. I am trying to implement Basemap changer through a list of base map collection of images. It is working fine but when the same base map selected twice then app crashes and showing map is nil.
I am attaching the screenshots along with code. It would very much appreciated if somebody help me to get rid of this error.
Thanks in advance
Hi.
The problem you're seeing is that you're trying to use an AGSLayer that is already being used. In Runtime, for performance reasons, many objects cannot be used (or "owned") by more than one other object. In this case, your AGSMap owns a AGSBasemap which owns the layer you are reusing (Coast_url). Your code is trying to create a new AGSBasemap with a layer that is already "owned" by map's current basemap.
If you look in the Xcode console, you will see the following when you try to create the new AGSMap.
ArcGIS Runtime Error Occurred. Set a breakpoint on C++ exceptions to see the original callstack and context for this error: Error Domain=com.esri.arcgis.runtime.error Code=24 "Object is already owned." UserInfo={NSLocalizedFailureReason=Already owned., NSLocalizedDescription=Object is already owned., Additional Message=Already owned.}
Instead, you will need to create an entirely new AGSArcGISMapImageLayer (or AGSArcGISTiledLayer) and use that in a new AGSBasemap. You could modify your code like this to achieve this, using an enum instead of strings…
enum CustomBasemap { enum Language { case EN case AR } case coast case satellite case hybrid(language: Language) case streetmap(language: Language) func getLayer() -> AGSLayer { switch self { case .coast: return AGSArcGISMapImageLayer(url: URL(string:"https://services.gisqatar.org.qa/server/rest/services/Vector/Coast/MapServer")!) case .satellite: return AGSArcGISTiledLayer(url: URL(string:"https://services.gisqatar.org.qa/server/rest/services/Imagery/QatarSatelitte/MapServer")!) case .hybrid(let language): switch language { case .EN: return AGSArcGISTiledLayer(url:URL(string: "https://services.gisqatar.org.qa/server/rest/services/Vector/Qatar_StreetMap_Hybrid_E/MapServer")!) case .AR: return AGSArcGISTiledLayer(url:URL(string: "https://services.gisqatar.org.qa/server/rest/services/Vector/Qatar_StreetMap_Hybrid_Ar_Test/MapServer")!) } case .streetmap(let language): switch language { case .EN: return AGSArcGISTiledLayer(url:URL(string: "https://services.gisqatar.org.qa/server/rest/services/Vector/Qatar_StreetMap_E/MapServer")!) case .AR: return AGSArcGISTiledLayer(url:URL(string: "https://services.gisqatar.org.qa/server/rest/services/Vector/Qatar_StreetMap_A/MapServer")!) } } } func getBasemap() -> AGSBasemap { return AGSBasemap(baseLayer: getLayer()) } }
and then set the basemap on the existing map (which will save you creating a new map and setting initialViewpoints):
var basemapType: CustomBasemap = .coast override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.map = AGSMap(basemap: basemapType.getBasemap()) self.mapView.map = self.map self.SetMapExtent() } ... func Coast_Map_Tapped() { basemapType = .coast self.map.basemap = basemapType.getBasemap() }
Hope that helps.
Dear Nicholas,
Thanks a lot for your solution of my problem. It is now working fine. You have explained very nicely and provided exact code. I am very grateful to you and hope you will help me in future as well.
Warm regards.
Angemeldete Mitglieder können Beiträge verfassen, Updates folgen und mehr. Neu hier? Registriere ein kostenloses Konto.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.