With ArcGIS Maps SDK for Swift, you can build applications that allow your users to perform specific operations on a map view and scene view, such as:
- Identify a feature in a map view.
- Set a view point with animation.
- Convert a screen coordinate to a geographical location.
- Export a scene view's image.
These operations are provided by the map view and scene view proxy structures called MapViewProxy
and SceneViewProxy
, respectively. MapView
and SceneView
structures conform to the SwiftUI.View protocol and provide view modifiers to customize the view's appearance or behavior. Proxies, however, are different and expose properties and methods that aren't suitable as a view's initializer parameter or a view modifier. Let's explore how to use map view and scene view proxy.
MapViewProxy and SceneViewProxy
The MapViewProxy
type exposes methods that you can perform on a map view. You don’t create instances of MapViewProxy
directly. Instead, you wrap your MapView
in a MapViewReader
and it exposes an instance of a MapViewProxy
in its closure. The proxy allows access to the map view's size, coordinate space, read-only properties, and methods that operate on the map or scene view itself. SwiftUI also adopts this coding pattern with the ScrollViewProxy and GeometryProxy.
The code below sets the map view's viewpoint scale once the map
has loaded. The MapViewReader
wraps the MapView
and exposes the map
in its closure. When the Map
is created, a task view modifier loads the map and calls the set
method on the map
as follows:
var body: some View {
// Wrap the MapView in MapViewReader and expose its MapViewProxy.
MapViewReader { mapViewProxy in
MapView(map: map, viewpoint: viewpoint)
// The task view modifier sets the view point scale
// after the map has loaded.
.task {
do {
try await map.load()
await mapViewProxy.setViewpointScale(1e7)
} catch {
self.error = error
}
}
}
}
To perform operations on a scene view, use SceneViewReader
, SceneView
, and SceneViewProxy
with the same coding pattern.
Examples
Display identify results in a PopupView
This example demonstrates how you can use the identify
operation to allow your users to tap on a map view and display the popup information for the first feature near that tapped location. A PopupView, provided by the ArcGIS Toolkit, displays the popup information in a floatingPanel on the map view.
Steps
-
Import the SwiftUI, ArcGIS and ArcGISToolkit frameworks into your application.
-
Instantiate a
Map
using a web map's portal item that contains a feature layer. -
Use the @State property wrapper to ensure that SwiftUI preserves the state of properties such as the
map
,identify
, the currentScreen Point popup
, and a boolean to indicate if the PopupView should be displayed. -
Instantiate the
MapView
with themap
and wrap it inMapViewReader
so that itsMapViewProxy
is exposed. -
Handle the map view's onSingleTapGesture and store the user's tapped point in the
tapped
property.Screen Point -
Specify an asynchronous task modifier to perform an action when the
tapped
value changes. In the task's closure, call the proxy's identifyLayers operation to identify features close to theScreen Point tapped
. Obtain the first identifyLayerResult, store its popup, and setScreen Point show
to true.Popup -
Set up a floatingPanel view modifier. Note: This is an ArcGISToolkit component.
-
Add the
popup
to a PopupView and display it within thefloating
. Note:Panel Popup
is also an ArcGISToolkit component.View
// Import frameworks.
import SwiftUI
import ArcGIS
import ArcGISToolkit
struct IdentifyView: View {
// Instantiate a map.
@State private var map = Map(
item: PortalItem(
portal: .arcGISOnline(connection: .anonymous),
id: .incidentsInSanFrancisco
)
)
// Preserve property state.
@State private var tappedScreenPoint: CGPoint
@State private var popup: Popup?
@State private var showPopup = false
var body: some View {
// Wrap the MapView in MapViewReader and expose its MapViewProxy.
MapViewReader { mapViewProxy in
MapView(map: map)
// Handle a single tap gesture. Save the tapped screen point.
.onSingleTapGesture { screenPoint, _ in
tappedScreenPoint = screenPoint
}
// Call the proxy's `identifyLayers` method when the value
// of the `tappedScreenPoint` property changes.
.task(id: tappedScreenPoint) {
guard let tappedScreenPoint = tappedScreenPoint,
let identifyResult = try? await mapViewProxy.identifyLayers(
screenPoint: tappedScreenPoint,
tolerance: 12,
returnPopupsOnly: false
)
else { return }
self.popup = identifyResult.first?.popups.first
self.showPopup = self.popup != nil
}
// Show the popup information in an PopupView and display
// it inside a FloatingPanel within the MapView.
// Note: These are ArcGIS Toolkit components.
.floatingPanel(
selectedDetent: .constant(.full),
horizontalAlignment: .leading,
isPresented: $showPopup
) { [popup] in
PopupView(popup: popup!, isPresented: $showPopup)
.showCloseButton(true)
.padding()
}
}
}
}
private extension PortalItem.ID {
/// The ID used in the "Incidents in San Francisco" portal item.
static var incidentsInSanFrancisco: Self { Self("fb788308ea2e4d8682b9c05ef641f273")! }
}
The code above displays a predefined popup for the identified feature as follows: