|
POST
|
Hi, Thanks for the question and the detailed info. In general, a map that gets into the hundreds of layers at a time raises some questions about the purpose or composition of the map. Given that a layer is meant to represent a type or category of data rather than a specific piece of data, you can see that 100 layers is a lot for a user to take in. Layers are database tables, not table rows, and you should really aim to consolidate data of one type into one table (i.e. layer). Often when you have that many types of data, they are for visual reference and best consolidated into a single layer (or basemap layer). That can be efficiently packaged up as a vector tile layer and often removes a lot of complexity. You mentioned a few things that I'd like to ask about: "approximately 1800 FeatureLayers from 9 different mmpks, with each mmpk containing between 20 to 1000 layers" - are you opening all the maps within these 9 MMPKs and selectively moving layers to your app's visible map? How large are the MMPKs? Are the data layers in each MMPK the same but include data for different geographies? Or are they 9 completely different sets of layers? "only those [layers] within the current viewing range are added" - do you mean visible geographic extent, or are you also considering scale range? Layers can be configured with a minScale and maxScale. I'm not sure that would help with performance in this case, but it's worth considering alongside other recommendations as it could simplify your code logic. Also, remember that Runtime will only load the data it needs for the visible extent. As you pan around the map, it will load more as needed. Unless you have other operational reasons to segregate your data by geography, you don't need to break it up that way for Runtime (in fact it can often complicate map content), though it should be an acceptable approach as long as you're removing layers you no longer display. When a layer or map is not being displayed, make sure you're not holding on to references to it. Consider the geometry types of these feature layers. Point layers render on the GPU in dynamic mode by default, and polyline/polygon layers render on the CPU in static mode. When adjacent layers in the layer stack all render in static mode, that static rendering is consolidated efficiently. However, if you have static and dynamic layers intermingled, each static layer is rendered independently and that's much more computationally expensive. You can explore a couple of things here: - A general good rule of thumb is order your layers by type. Polygons on the bottom, then polylines, then points. That aligns nicely with removing interleaving of static and dynamic layers. - You can control the rendering mode of feature layers (though there are some cases, like heat map renderers, where you can't), so if you do need to retain some interleaving of polyline or polygon layers between point layers, you can explicitly set the rendering mode on those polyline/polygon layers to dynamic to see if that helps. In a lot of situations, dynamic mode works well on polyline and polygon layers. If you have multiple layers showing the same kinds of data with the same symbology/renderers, then that can be wasteful. It's much more efficient if that data is merged into one layer, and at that point Runtime can render all that data with one renderer instance and do a lot more resource sharing within the rendering pipeline. If you are able to join multiple layers showing the same kind of data into one layer, you can use displayFilters and/or definitionExpressions to limit the features that are displayed at any given time. If you have picture marker symbol based off bitmaps/images, how large are those bitmaps? Each bitmap must be kept in memory in the GPU, and possibly also in the CPU as part of the renderer definition. If you have multiple layers using the same bitmap, that is wasteful (see previous bullet - if you can consolidate like layers into one, that will probably benefit you a lot). Likewise, if the bitmap is higher resolution than is needed for displaying the symbol, that can also lead to waste. Consider the renderers defined on each layer. When a layer is loaded and displayed, that renderer is created and lives in memory. For example, do you have multiple unique value renderers that use large bitmaps? It's not that unique value renderers themselves are expensive (in fact, they are a very efficient way to render given that we can do a lot of resource sharing in the GPU), but if you have higher-resolution bitmaps in use then a UVR is a quick way to multiply that problem. Also think about the spatial reference of the feature layer data in the MMPKs. If you're using a Web Mercator basemap (as all our standard basemaps are) but the data is in another spatial reference, then it must be projected on the fly. With this much data this could be impacting performance. You can see more discussion on this and other performance considerations here: https://developers.arcgis.com/ios/programming-patterns/performance-considerations/ To answer your questions: Could the sheer number of layers within each mmpk be the cause of these performance issues? Yes. Is merging layers a potential solution? Definitely. Also consider whether any layers can be consolidated into a single vector tile layer. Remember you can't interrogate vector tile layers to read attributes though - they're purely for visual reference. What is the recommended number of layers within a single mmpk? We can't really give a hard number. It depends a lot on how many are visible at any one time with scale ranges, and what type of layer it is, and the complexity/density of the data. But from experience I would say that if you have over 150 layers, you should really be looking at how you're authoring your map. However if layers have complex renderers or complex data, you could start seeing the impact sooner. Personally, I start to ask myself questions if my map has over 50 layers. Not from a performance perspective, but from a "just what is my map supposed to be doing" perspective. Sometimes the answer is "Yeah, it does need all those", but often it's a chance to simplify. It's also a bit different since (if I understand correctly) you're not displaying all the layers at once and are consolidating things from multiple MMPKs into one Map. It's what ends up in that map that is probably more important here. What is the recommended size for each layer in terms of square kilometers? There isn't a limit. They can be global, and I don't think the geographic extent of your data is a concern here. The spatial indexing on the data ensures that data is read from the MMPK's internal data store very efficiently by geography. However, make sure that your layers have suitable minScale and maxScale defined so that data isn't displayed at inappropriate zoom levels. Also note that when accessing an ArcGIS service, data is generalized for display by the server when it's requested, but in an MMPK the data in the MMPK is raw and no generalization happens until the data has been read from the MMPK and passed to the GPU for rendering. Vector tile layers can help with this. Also, if the data needs to remain as feature layers and you need to see complicated polylines and polygons at a large range of scales, consider including a generalized copy of that data in the MMPK as a separate layer. Use scale ranges on the layers so that when zoomed out you view the generalized data and when zoomed in you view the original denser data. You'll take a hit on the size of the MMPK, but will buy yourself a better experience viewing the data. It's not typically necessary, but worth bearing in mind. Hopefully the above ideas will help you reduce the number of layers you're working with, which is almost certainly the primary thing you should focus on. But I am guessing a lot about what you might be doing and how your data is authored. If you need more help then (depending on where you are globally) I would probably recommend a Professional Services engagement to dig deeper into your data workflows and use cases. Or if you have an Esri account manager or local distributor that you're working with, perhaps reach out to them and see if they have a preferred approach to getting some one-on-one help.
... View more
11-17-2023
09:56 AM
|
3
|
2
|
2546
|
|
POST
|
Hello. The 200.x ArcGIS Native SDKs for Native Apps (and 100.x ArcGIS Runtime SDKs) do not include any form of encryption; you don't need to submit any export compliance documentation because of the SDKs. Hope that helps. I'll see if we can include this information in the deployment pages. It doesn't come up often but I think it's a reasonable question.
... View more
10-24-2023
02:47 PM
|
1
|
0
|
1206
|
|
POST
|
You need to create a AGSMobileMapPackage pointing at the folder you downloaded the offline map to. Load the AGSMobileMapPackage, then get the map from the maps collection. You can see that covered here. Unfortunately the iOS SDK code snippet has been removed, but you can get the gist from the Swift SDK snippet. https://developers.arcgis.com/documentation/mapping-apis-and-services/offline/offline-maps/working-with-offline-maps/#access This doc is admittedly a little hard to find. We're working on revised and improved offline doc that should make this easier to discover.
... View more
10-05-2023
08:01 AM
|
1
|
1
|
1666
|
|
POST
|
Hi, To take a custom area of a map offline, you will need to use the On-Demand workflow. Each area that you download will be a separate offline map. So, for example, if you download two overlapping areas, they will be separate offline maps on your device and are not merged. You can learn more about the overall offline capabilities here.
... View more
08-21-2023
08:04 AM
|
0
|
0
|
780
|
|
POST
|
What's the crash once you have the correct signature for showSublayersDialog()? It should be different to the one in your original posting.
... View more
08-17-2023
08:36 AM
|
0
|
0
|
4927
|
|
POST
|
Hi Jonas! You can do this by setting the reference scale on the ArcGISMap, and then specifying that your feature layer should scale symbols. You might need to do some experimenting to get the behavior you want. Let us know how this works for you.
... View more
08-16-2023
09:53 AM
|
0
|
0
|
683
|
|
POST
|
The EstimateTileCacheSizeJob only works on image tile services. Vector Tile Services do not support an estimate operation. Are you sure you are calling EstimateTileCacheSizeJob on the vector tile service to get your number of 3180866? That should fail.
... View more
08-16-2023
08:56 AM
|
0
|
0
|
669
|
|
POST
|
I'm not an Android/Kotlin developer, but it looks like your signature for showSublayersDialog() is wrong. It looks like you need it to accept a View parameter (e.g. showSublayersDialog(View v)). See this documentation on the android:onClick attribute. The doc indicates that method should be public, but it looks like that's the default visibility for Kotlin, so you could be OK there.
... View more
08-16-2023
08:49 AM
|
0
|
0
|
4938
|
|
POST
|
As I mentioned in my response to your other question, there are many things to consider when taking data offline. What extent do you need (sounds like you want all of India, but often you only need areas where there is no network coverage for accessing services), what zoom levels do you need (it seems you want all zoom levels), and which basemap (Imagery? Streets?). For your requirements, just downloading the basemap from a service will not be practical, and may not even be possible (a basemap for all of India with full zoom levels will result in a very large file). But there are other ways to get this data, like with a product such as StreetMap Premium. I would suggest you contact your local Esri distributor to discuss options. If you're in India, that would be Esri India: https://www.esri.in/ They will be able to help you determine the best approach for your application, and provide the support you need to implement your solution.
... View more
08-11-2023
07:47 AM
|
0
|
4
|
3848
|
|
POST
|
You can find an example here: https://developers.arcgis.com/java/sample-code/export-tiles/ In that code, an area of the basemap is downloaded (exported) as a TPK (you can learn more about that here), and used to create a new basemap and a new map. Once it's downloaded to your device, you can just use it whenever you create a new map. If you need more help with this, please ask a new question as requested previously.
... View more
08-08-2023
08:26 AM
|
0
|
1
|
1292
|
|
POST
|
Hi @PRAVEENPATNANA, As Colin mentioned, offline is a complex topic and there are a few ways you approach it. There is a diagram on this page which helps summarize where data comes from for offline work. You're already working with "Data files" with your shape file. What you have noticed is that you will also need to get a basemap to use offline. So far, you have been using our basemap service to use the basemap over the internet. There is no magic button that suddenly makes a basemap work offline. You have to deliberately download it first (either from our basemap service, or from a file you create using ArcGIS Pro). You will need to think about the requirements of your app to decide the best approach. Things to consider are zoom levels and overall extent. A basemap for all of India at all zoom levels will be huge and would take a long time to download. If you don't need to zoom in far, then you could create a basemap that is only used when zoomed out and that could be a lot smaller. Ultimately, you will have to think about how you need to use your data and the basemap offline. This video could also help: https://www.youtube.com/watch?v=VTD2omhGVdI I would also suggest that if you have further questions on this topic that you start a new thread so that other developers can find the discussion more easily (this thread started out as a question about Shapefiles in JavaFX). Hope that helps.
... View more
08-07-2023
10:08 AM
|
0
|
4
|
1327
|
|
POST
|
Declaring map as optional means that it can be nil at some point. Your crash was because by using "!" you had said "I know it will never be nil when I use it", but it turned out it was nil. If you declare it as optional with "?", then Swift will check if the map is nil. You won't get a crash, but your code might be skipped. And you must include logic to acknowledge that it could be nil when you're using it. One common approach is optional binding using an "if let" block. So your code above could be included in an "if let" block: func Load_Municipality_Boundary() {
if let map = map {
self.munFeatureTable = AGSServiceFeatureTable(url: munCensus)
let munFeatureLayer = AGSFeatureLayer(featureTable: self.munFeatureTable)
map.operationalLayers.add(munFeatureLayer)
let censusFeatureTable = AGSServiceFeatureTable(url: URL(string: "https://services.gisqatar.org.qa/server/rest/services/Vector/Census_Municipality/FeatureServer/1")!)
map.tables.addObjects(from: [censusFeatureTable])
mapView.selectionProperties.color = .yellow
self.munFeatureLayer = munFeatureLayer
} else {
print("Map is not set!!")
}
} That "if {}" block will only execute if map is not nil. It's still up to you to make sure the "map" variable is set to an AGSMap instance, or you will see a "Map is not set!!" message written to the console. Optional variables are a fundamental Swift pattern, and not something specific to the ArcGIS Runtime SDK for iOS. I suggest you familiarize yourself with how optional variables are used in Swift. There are many tutorials and articles available online, such as this one. Ultimately though, you need to work out why your app is setting "map" to nil at some point, and make sure that you set the "map" variable to a new AGSMap again before you use it in the above code.
... View more
08-01-2023
08:07 AM
|
0
|
0
|
2635
|
|
POST
|
Beware the exclamation mark. This code is dangerous: var map: AGSMap! Declaring map as an implicitly unwrapped optional is stating that even though the variable is optional and can be nil, that you KNOW that whenever you access it, it will not be nil. Unfortunately, in your app, that's not the case. When you click "Maps" a second time and SetMapExtent() is called, the map variable above is nil. Make sure that it isn't and your code will get a bit further. But I would recommend not declaring it as an implicitly unwrapped optional in the first place. func SetMapExtent () {
let envelope = AGSEnvelope (xMin:216985.909, yMin:375531.776, xMax:241940.565, yMax:415497.915, spatialReference: self.mapView.spatialReference)
self.map.initialViewpoint = AGSViewpoint(targetExtent: envelope)
self.mapView.map = map
} However, self.mapView.spatialReference is also nil, so the envelope you create will have a nil spatial reference. That will also probably cause problems.
... View more
07-27-2023
06:57 AM
|
0
|
1
|
2667
|
|
POST
|
Hi. It looks like you've answered this yourself already. See your other question. The first place to look for samples in our samples app. Here's a KML sample, which you might already have found.
... View more
07-24-2023
09:49 AM
|
0
|
0
|
707
|
|
POST
|
Hello. You need a Standard license to access KML files stored locally on your device (see the licensing documentation). It looks like you have applied a license, but it is not a Standard license. Note that during development and testing (by not applying a license) you can test using a local KML file, but your app will have a watermark and you cannot deploy to production. Also note that KML accessed via the web (e.g. via https) can be used with a Lite license. Hope that helps.
... View more
07-24-2023
09:41 AM
|
0
|
0
|
785
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 11-05-2025 10:52 AM | |
| 1 | 11-04-2025 08:55 AM | |
| 1 | 11-04-2025 08:38 AM | |
| 1 | 11-01-2025 03:25 PM | |
| 1 | 10-29-2025 10:28 AM |