|
POST
|
Ah. I misread your previous post and thought you had wanted to lock the scale. My mistake 😬 But yes, that's what setting DistanceInteractive to false would have done. But I'm a little surprised that your solution does what you want. The constructor you're using for OrbitLocationCameraController takes a focus point, and a distance from that focus point. What you have would work if the camera is looking straight down from directly above the point you're looking at, and if the elevation of the point you're looking at is 0. I would expect that if you take your new code (with setViewpoint code in the else block), but use the OrbitLocationCameraController constructor from your original snippet, then you would get precisely what you want.
... View more
05-25-2021
08:08 AM
|
0
|
0
|
2888
|
|
POST
|
Looks like what you're doing should get you close. But rather than setting the viewpoint (which is already what you want), get the viewpoint, create an OrbitLocationCameraController (as you are doing) using the viewpoint geometry and the current camera's location, and then set the camera controller's DistanceInteractive to false. Does that work for you?
... View more
05-24-2021
07:36 AM
|
0
|
2
|
2901
|
|
POST
|
Sounds like you really want to use multiple Graphics, where each graphic's geometry is a single point rather than a single graphic with a multipoint geometry. However, you could use GeometryEngine.nearestVertex(), passing in the identified multipoint geometry and the identify map location. This returns a ProximityResult which includes a partIndex and pointIndex.
... View more
05-20-2021
09:43 AM
|
0
|
1
|
2114
|
|
POST
|
Yes. You can get the center of the current viewpoint by calling GeoView::currentViewpoint() and passing in a viewpoint type of CenterAndScale (a GeoView could be a MapView (2D) or a SceneView (3D)). The Viewpoint you get back has a targetGeometry, which in this case will be a Point representing the center of the map/scene view. Since you want lat/lon… The units of x/y coordinates of the center point will depend on the spatial reference of the map/scene view. If you know it's WGS84, you're good. But if you don't know, or you know it's something else (a map using our basemaps will likely be Web Mercator), then you can use GeometryEngine to easily project that point to WGS84 and then get the Lat Lon. Note, lat/lon is y/x, not x/y.
... View more
05-20-2021
09:28 AM
|
1
|
4
|
2939
|
|
POST
|
Hmm. Do you mean the AGSGenerateOfflineMapResult you get back has layerErrors, and one of those errors is "Layer type unsupported"? If the entire job is passing an error to the completion block, make sure that AGSGenerateOfflineMapParameter.continueOnError is true when you create the download job. The Offline Map Task works against a web map. This custom layer cannot be added to a web map, so I don't think it could be the cause there. You can see the types of layers that are supported listed here. Does your web map have some other type of layer, like a dynamic map service layer? Also, be aware that the service behind the layer must be configured to support offline workflows (although I would expect a different error message in that case). Once you've got to the bottom of that, there are a couple of possible approaches I can think of. Save the web map with the original layer included, but leave the visibility off. When it comes time to generate the offline map, the original layer should be included, and you can turn the visibility on once you get the offline map. Configure the onlineOnlyServicesOption to download the offline map, but including references to layers that can't be taken offline. Unfortunately, packing up image tile services can take a long time as the server must collect all the tiles and build a tile package from them. Another option, if the service owner's data license allows it, is to modify the code above to write tiles to the local device. When asked for a tile, if the tile is already present, just read it from the device, otherwise go and retrieve it from the service (writing it to disk when you get it and before you hand it back to Runtime in the respond(with:data:error:) call). You would need to write cache control logic to delete tiles (you don't want to just fill up the device with downloaded tiles!). Note: this is against our terms for ArcGIS basemap services, but it sounds like you are using someone's custom tile service, so they might allow this.
... View more
05-17-2021
02:33 PM
|
0
|
0
|
2112
|
|
BLOG
|
The 100.11.1 release of the ArcGIS Runtime SDK for iOS resolves an issue discovered when using OAuth workflows in iOS 14.5 with ArcGIS Runtime 100.11.0. To summarize, ArcGIS Runtime SDK for iOS release 100.11 adopts Apple's recommended approach for handling OAuth authentication, using ASWebAuthenticationSession. Unfortunately, iOS 14.5 updated the behavior of ASWebAuthenticationSession which resulted in crashes when using Runtime 100.11.0 with typical ArcGIS OAuth configurations (Debug builds only). The 100.11.1 release of the ArcGIS Runtime SDK for iOS resolves this issue. No code changes are required in your apps. Simply ensure you are using the 100.11.1 release. Default CocoaPods and Swift Package Manager configurations just need a package refresh; if you have explicitly set a dependency version of 100.11.0, you will need to update your configuration. ArcGIS Runtime SDKs for .NET and Qt applications targeting iOS are not affected by this issue.
... View more
05-13-2021
10:29 AM
|
0
|
0
|
1118
|
|
POST
|
Hi. Yes it does. You need to have an MMPK that includes locator data. When you create your own MMPK in ArcGIS Pro, you have the option to include your locator when you export it. Or if you want to use the StreetMap Premium packages, they include a locator. You can see an example of using geocoding from an MMPK here (pick the ArcGIS iOS API from the example drop down). That example is the minimum needed to get the locator and do a search with it. You only need to load the AGSMobileMapPackage and create the AGSLocator once, and can then call geocode() as much as you like on it. You can see another example here (that assumes the MMPK (indianaPackage) is already loaded). You can test this out with a sample MMPK we have available for the Greater Los Angeles area. See here. Does this help?
... View more
05-13-2021
09:11 AM
|
1
|
0
|
1040
|
|
POST
|
Hi @g3oapp. Just following up. Are you considering updating to 100.11? We think there's a good chance this will resolve this issue for you.
... View more
05-12-2021
12:44 PM
|
0
|
0
|
3119
|
|
POST
|
Do you really need to authenticate the Task per user? You end up creating a GeoprocessingJob from the task. That has a Credential property on it. Are you able to set that to the new ArcGISTokenCredential as in your sample code before you await on the job's GetResultAsync()? I.e. use a single credential to get the task's metadata using the challenge handler (feels like it could be an App Login credential), and then use each client's token for each job before you get the results. However, Runtime is not designed to run in a service (you may hit design or technical issues, as here) and it's also against the terms of use (see footnote 19, applying to the ArcGIS Runtime SDKs under the Developer Products section, in the Product-Specific Terms of Use). That said, we are always looking to understand how we can better support customer use cases, so I'd be interested in understanding more about what you're doing here. Is it possible you could do it by shifting stuff to the client? After all, the GeoprocessingJob Runtime object is really just performing some lightweight polling of the actual server-side GP job. For example: What are the clients that are hitting your service written in (are they mobile apps, or web apps)? Since they're already passing in a token, can they hit the GP Task directly and create and manage a Job? Is there something you need from the Runtime after the job completes to process the results before passing them back to the client? Typically, these things can be done in the client.
... View more
05-12-2021
11:04 AM
|
0
|
0
|
2527
|
|
POST
|
Simply updating the builder will not update the graphic's geometry. After you removeAll() on the builders, you need to set the geometry on wayPointMakeGraphic and wayPointLineMakeGraphic from the builders again, as you do in your onMouseClicked method. This should set the geometries on the graphics to valid, but empty geometries.
... View more
05-10-2021
09:28 AM
|
0
|
1
|
1638
|
|
POST
|
Hi @Shimoorook, We are working on a Swift version of the Runtime SDK for iOS that will work directly with Swift UI, but it won't be available before 2022. At this time we don't have anything we can share but we intend to spin up a beta program, hopefully later this year. Watch this space for an announcement. In the meantime, you could start with Apple's tutorial that uses MapKit and replace the MapKit Map with Runtime's AGSMap. We hope to have some samples available before too long.
... View more
05-06-2021
08:26 AM
|
0
|
0
|
4947
|
|
POST
|
Correct. .blank will do that. By default any lower resolution tile that is available will be upscaled.
... View more
05-05-2021
02:12 PM
|
1
|
0
|
2206
|
|
POST
|
Out of interest, what do you want the behavior to be when you hit your limiting criteria? But you should be creating an AGSImageTiledLayer with an AGSTileInfo and a full extent. See AGSImageTiledLayer(CustomImageTiledLayer). Since you're working with an ArcGIS service for the layer, you can just lift that directly from the service. This code works well (you should probably modify the tileCount code - I've put no effort into making it thread safe and am relying on the tileRequestHandler being called on the main queue to force sequential access to tileCount) : import UIKit
import ArcGIS
class ViewController: UIViewController {
@IBOutlet weak var mapView: AGSMapView!
let layerURL = URL(string: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer")!
var tileCount = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let metadataLayer = AGSArcGISTiledLayer(url: layerURL)
metadataLayer.load { [weak self] (error) in
guard let self = self else { return }
if let error = error {
print("Error loading layer: \(error.localizedDescription)")
return
}
if let tileInfo = metadataLayer.tileInfo,
let fullExtent = metadataLayer.fullExtent {
let customLayer = AGSImageTiledLayer(tileInfo: tileInfo, fullExtent: fullExtent)
// This highlights how tiles are not retrieved
customLayer.noDataTileBehavior = .blank
customLayer.tileRequestHandler = { [weak self, layerURL = self.layerURL] tileKey in
guard let self = self else { return }
guard self.tileCount < 4 else {
// Note, the first tile (global tile at zoom 0) might not be displayed as it
// is superceded by tiles at zoom level 1.
customLayer.respondWithNoDataTile(for: tileKey)
return
}
self.tileCount += 1
let tileUrl = layerURL
.appendingPathComponent("tile")
.appendingPathComponent("\(tileKey.level)")
.appendingPathComponent("\(tileKey.row)")
.appendingPathComponent("\(tileKey.column)")
// print("\(self.tileCount) \(tileUrl.path)")
// Piggy back on ArcGIS Authentication with AGSRequestOperation
let tileOp = AGSRequestOperation(url: tileUrl)
tileOp.registerListener(customLayer) { [weak customLayer] (tileData, error) in
guard let customLayer = customLayer else { return }
guard let tileData = tileData as? Data else {
customLayer.respondWithNoDataTile(for: tileKey)
return
}
customLayer.respond(with: tileKey, data: tileData, error: error)
}
AGSOperationQueue.shared().addOperation(tileOp)
}
let basemap = AGSBasemap(baseLayer: customLayer)
self.mapView.map = AGSMap(basemap: basemap)
}
}
}
}
... View more
05-05-2021
01:52 PM
|
1
|
0
|
2210
|
|
POST
|
Thanks. The team wants to confirm that the call stack is consistent when you see the crash (i.e. it's not crashing in the same spot via some other route). However, we improved the internals of tiling with 100.11 and sql_cache_tile_provider has been removed. Are you planning on updating to 100.11?
... View more
05-04-2021
08:46 AM
|
0
|
1
|
3183
|
|
POST
|
Hi @FatmaAkdemir, Good question. There are two things in play here. Your paid developer subscription level (the ADS code), and your app's functionality (the license string). The ADS code is unrelated to the license string. The ADS (ArcGIS Developer Subscription) code identifies your paid subscription and can be used at My Esri to link your paid developer subscription with your My Esri page, so you can have easy access to the various resources (downloads, tools, support, etc.) that are available to you, depending on the paid subscription level. The license string is only used in your Runtime app. It removes the watermark and enables specific Runtime functionality in your app when it is released to production. The Runtime capabilities your production Runtime app depends on the license string you use (Lite, Basic, Standard, or Advanced). Note that everyone gets a free Lite license string to use in their apps. Your Standard license string enables additional capabilities as described at the link above. Without a license string, you are in development and test mode: all Runtime capabilities are enabled but you will see the watermark. You are required to use a license string to release any Runtime app. Hope that helps.
... View more
05-03-2021
09:47 AM
|
0
|
0
|
3377
|
| Title | Kudos | Posted |
|---|---|---|
| 2 | 05-14-2026 07:07 AM | |
| 2 | 04-30-2026 10:59 AM | |
| 4 | 04-22-2026 08:07 AM | |
| 1 | 01-29-2026 09:39 AM | |
| 1 | 12-17-2025 10:12 AM |