Skip to content

Commit 04c6bbb

Browse files
authored
Merge pull request #172 from Esri/v.next
[Release] 200.1.0
2 parents 5992329 + e70be07 commit 04c6bbb

File tree

108 files changed

+5820
-1049
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+5820
-1049
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 27 deletions
This file was deleted.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ This repository contains Swift sample code demonstrating the capabilities of [Ar
44

55
## Requirements
66

7-
* [ArcGIS Maps SDK for Swift](https://developers.arcgis.com/swift/) 200.0 (or newer)
8-
* [ArcGIS Maps SDK for Swift Toolkit](https://github.com/Esri/arcgis-maps-sdk-swift-toolkit) 200.0 (or newer)
7+
* [ArcGIS Maps SDK for Swift](https://developers.arcgis.com/swift/) 200.1 (or newer)
8+
* [ArcGIS Maps SDK for Swift Toolkit](https://github.com/Esri/arcgis-maps-sdk-swift-toolkit) 200.1 (or newer)
99
* Xcode 14.0 (or newer)
1010

1111
The *ArcGIS Maps SDK for Swift Samples app* has a *Target SDK* version of *15.0*, meaning that it can run on devices with *iOS 15.0* or newer.
@@ -44,7 +44,7 @@ Please see [Configure App Secrets](Documentation/ConfigureAppSecrets.md) for add
4444
* Unfamiliar with SwiftUI? Check out Apple's [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/).
4545
* Want to start a new project? [Setup](https://developers.arcgis.com/swift/get-started) your development environment
4646
* New to the API? Explore the documentation: [Guide](https://developers.arcgis.com/swift/) | [API Reference](https://developers.arcgis.com/swift/api-reference/documentation/arcgis/)
47-
* Got a question? Ask the community on our [forum](https://community.esri.com/t5/arcgis-runtime-sdk-for-ios-questions/bd-p/arcgis-runtime-sdk-for-ios-questions)
47+
* Got a question? Ask the community on our [forum](https://community.esri.com/t5/swift-maps-sdk-questions/bd-p/swift-maps-sdk-questions)
4848

4949
## Contributing
5050

@@ -54,7 +54,7 @@ Find a bug or want to request a new feature? Please let us know by [creating an
5454

5555
## Licensing
5656

57-
Copyright 2022 Esri
57+
Copyright 2022 - 2023 Esri
5858

5959
Licensed under the Apache License, Version 2.0 (the "License");
6060
you may not use this file except in compliance with the License.

Samples.xcodeproj/project.pbxproj

Lines changed: 277 additions & 6 deletions
Large diffs are not rendered by default.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2023 Esri
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import SwiftUI
16+
import ArcGIS
17+
18+
extension AddDynamicEntityLayerView {
19+
/// The model used to store the geo model and other expensive objects
20+
/// used in this view.
21+
class Model: ObservableObject {
22+
/// A map with a streets basemap style.
23+
let map = Map(basemapStyle: .arcGISStreets)
24+
25+
/// The data source for the dynamic entity layer.
26+
let streamService: ArcGISStreamService = {
27+
let streamService = ArcGISStreamService(url: .streamService)
28+
29+
let filter = ArcGISStreamServiceFilter()
30+
filter.whereClause = "speed > 0"
31+
streamService.filter = filter
32+
33+
streamService.purgeOptions.maximumDuration = TimeInterval(5 * 60)
34+
return streamService
35+
}()
36+
37+
/// The layer displaying the dynamic entities on the map.
38+
let dynamicEntityLayer: DynamicEntityLayer
39+
40+
/// A Boolean value indicating whether track lines should be displayed.
41+
@Published var showsTrackLine: Bool {
42+
didSet {
43+
dynamicEntityLayer.trackDisplayProperties.showsTrackLine = showsTrackLine
44+
}
45+
}
46+
47+
/// A Boolean value indicating whether previous observations should be displayed.
48+
@Published var showsPreviousObservations: Bool {
49+
didSet {
50+
dynamicEntityLayer.trackDisplayProperties.showsPreviousObservations = showsPreviousObservations
51+
}
52+
}
53+
54+
/// The maximum number of previous observations to display.
55+
@Published var maximumObservations: CGFloat {
56+
didSet {
57+
dynamicEntityLayer.trackDisplayProperties.maximumObservations = Int(maximumObservations)
58+
}
59+
}
60+
61+
/// The maximum observations range.
62+
/// Used by slider, which requires `CGFloat` values.
63+
let maxObservationRange = CGFloat(1)...CGFloat(16)
64+
65+
/// The stream service connection status.
66+
@Published var connectionStatus: String
67+
68+
init() {
69+
// Creates the dynamic entity layer.
70+
dynamicEntityLayer = DynamicEntityLayer(dataSource: streamService)
71+
72+
// Initializes properties from the dynamic entity layer and stream service.
73+
showsTrackLine = dynamicEntityLayer.trackDisplayProperties.showsTrackLine
74+
showsPreviousObservations = dynamicEntityLayer.trackDisplayProperties.showsPreviousObservations
75+
maximumObservations = CGFloat(dynamicEntityLayer.trackDisplayProperties.maximumObservations)
76+
connectionStatus = streamService.connectionStatus.description
77+
78+
// Adds the dynamic entity layer to the map's operational layers.
79+
map.addOperationalLayer(dynamicEntityLayer)
80+
}
81+
}
82+
}
83+
84+
private extension URL {
85+
static let streamService = URL(
86+
string: "https://realtimegis2016.esri.com:6443/arcgis/rest/services/SandyVehicles/StreamServer"
87+
)!
88+
}
89+
90+
extension ConnectionStatus: CustomStringConvertible {
91+
/// A user-friendly string for `ConnectionStatus`.
92+
public var description: String {
93+
switch self {
94+
case .connecting:
95+
return "Connecting"
96+
case .connected:
97+
return "Connected"
98+
case .disconnected:
99+
return "Disconnected"
100+
case .failed:
101+
return "Failed"
102+
@unknown default:
103+
return "Unknown"
104+
}
105+
}
106+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2023 Esri
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import SwiftUI
16+
17+
extension AddDynamicEntityLayerView {
18+
struct SettingsView: View {
19+
/// The view model for the sample.
20+
@EnvironmentObject private var model: Model
21+
22+
var body: some View {
23+
List {
24+
Section("Track display properties") {
25+
Toggle("Track Lines", isOn: $model.showsTrackLine)
26+
Toggle("Previous Observations", isOn: $model.showsPreviousObservations)
27+
}
28+
29+
Section("Observations") {
30+
VStack {
31+
HStack {
32+
Text("Observations per track")
33+
Spacer()
34+
Text(model.maximumObservations.formatted())
35+
.foregroundColor(.secondary)
36+
}
37+
Slider(value: $model.maximumObservations, in: model.maxObservationRange, step: 1)
38+
}
39+
HStack {
40+
Spacer()
41+
Button("Purge All Observations") {
42+
Task {
43+
try? await model.streamService.purgeAll()
44+
}
45+
}
46+
Spacer()
47+
}
48+
}
49+
}
50+
}
51+
}
52+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2023 Esri
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import SwiftUI
16+
import ArcGIS
17+
18+
struct AddDynamicEntityLayerView: View {
19+
/// The view model for the sample.
20+
@StateObject private var model = Model()
21+
22+
/// A Boolean value indicating whether the settings view should be presented.
23+
@State var isShowingSettings = false
24+
25+
/// The initial viewpoint for the map.
26+
@State var viewpoint = Viewpoint(
27+
center: Point(x: -12452361.486, y: 4949774.965),
28+
scale: 200_000
29+
)
30+
31+
/// A Boolean value indicating if the stream service is connected.
32+
var isConnected: Bool {
33+
model.streamService.connectionStatus == .connected
34+
}
35+
36+
var body: some View {
37+
// Creates a map view to display the map.
38+
MapView(map: model.map, viewpoint: viewpoint)
39+
.toolbar {
40+
ToolbarItemGroup(placement: .bottomBar) {
41+
Button(isConnected ? "Disconnect" : "Connect") {
42+
Task {
43+
if isConnected {
44+
try? await model.streamService.disconnect()
45+
} else {
46+
try? await model.streamService.connect()
47+
}
48+
}
49+
}
50+
Spacer()
51+
Button("Dynamic Entity Settings") {
52+
isShowingSettings = true
53+
}
54+
.sheet(isPresented: $isShowingSettings, detents: [.medium], dragIndicatorVisibility: .visible) {
55+
SettingsView()
56+
.environmentObject(model)
57+
}
58+
}
59+
}
60+
.overlay(alignment: .top) {
61+
HStack {
62+
Text("Status:")
63+
Text(model.connectionStatus)
64+
.italic()
65+
}
66+
.frame(maxWidth: .infinity)
67+
.padding(.vertical, 6)
68+
.background(.thinMaterial, ignoresSafeAreaEdges: .horizontal)
69+
}
70+
.task {
71+
// This will update `connectionStatus` when the stream service
72+
// connection status changes.
73+
for await status in model.streamService.$connectionStatus {
74+
model.connectionStatus = status.description
75+
}
76+
}
77+
}
78+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Add dynamic entity layer
2+
3+
Display data from an ArcGIS stream service using a dynamic entity layer.
4+
5+
![Image of add dynamic entity layer](add-dynamic-entity-layer.png)
6+
![Image of add dynamic entity layer settings](add-dynamic-entity-layer-settings.png)
7+
8+
## Use case
9+
10+
A stream service is a type of service provided by ArcGIS Velocity and GeoEvent Server that allows clients to receive a stream of data observations via a web socket. ArcGIS Maps SDK allows you to connect to a stream service and manage the information as dynamic entities and display them in a dynamic entity layer. Displaying information from feeds such as a stream service is important in applications like dashboards where users need to visualize and track updates of real-world objects in real-time.
11+
12+
Use `ArcGISStreamService` to manage the connection to the stream service and purge options to manage how much data is stored and maintained by the application. The dynamic entity layer will display the latest received observation, and you can set track display properties to determine how to display historical information for each dynamic entity. This includes the number of previous observations to show, whether to display track lines in-between previous observations, and setting renderers.
13+
14+
## How to use the sample
15+
16+
Use the controls to connect to or disconnect from the stream service, modify display properties in the dynamic entity layer, and purge all observations from the application.
17+
18+
## How it works
19+
20+
1. Create an `ArcGIStreamService` using a stream service URL.
21+
2. Set an `ArcGISStreamServiceFilter` on the stream service to limit the amount of data coming from the server.
22+
3. Set the `maximumDuration` property of the stream service's `purgeOptions` to limit the amount of data managed by the application.
23+
4. Create a `DynamicEntityLayer` using the stream service.
24+
5. Update values in the layer's `trackDisplayProperties` to customize the layer's appearance.
25+
6. Add the `DynamicEntityLayer` to the map.
26+
27+
## Relevant API
28+
29+
* ArcGISStreamService
30+
* ArcGISStreamServiceFilter
31+
* ConnectionStatus
32+
* DynamicEntity
33+
* DynamicEntityDataSource.PurgeOptions
34+
* DynamicEntityLayer
35+
* TrackDisplayProperties
36+
37+
## About the data
38+
39+
This sample uses a [stream service](https://realtimegis2016.esri.com:6443/arcgis/rest/services/SandyVehicles/StreamServer) that simulates live data coming from snowplows near Sandy, Utah. There are multiple vehicle types and multiple agencies operating the snowplows.
40+
41+
## Tags
42+
43+
data, dynamic, entity, live, purge, real-time, service, stream, track
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"category": "Layers",
3+
"description": "Display data from an ArcGIS stream service using a dynamic entity layer.",
4+
"ignore": false,
5+
"images": [
6+
"add-dynamic-entity-layer-settings.png",
7+
"add-dynamic-entity-layer.png"
8+
],
9+
"keywords": [
10+
"data",
11+
"dynamic",
12+
"entity",
13+
"live",
14+
"purge",
15+
"real-time",
16+
"service",
17+
"stream",
18+
"track",
19+
"ArcGISStreamService",
20+
"ArcGISStreamServiceFilter",
21+
"ConnectionStatus",
22+
"DynamicEntity",
23+
"DynamicEntityDataSource.PurgeOptions",
24+
"DynamicEntityLayer",
25+
"TrackDisplayProperties"
26+
],
27+
"redirect_from": [],
28+
"relevant_apis": [
29+
"ArcGISStreamService",
30+
"ArcGISStreamServiceFilter",
31+
"ConnectionStatus",
32+
"DynamicEntity",
33+
"DynamicEntityDataSource.PurgeOptions",
34+
"DynamicEntityLayer",
35+
"TrackDisplayProperties"
36+
],
37+
"snippets": [
38+
"AddDynamicEntityLayerView.swift",
39+
"AddDynamicEntityLayerView.Model.swift",
40+
"AddDynamicEntityLayerView.SettingsView.swift"
41+
],
42+
"title": "Add dynamic entity layer"
43+
}
23.5 KB
Loading
36.8 KB
Loading

0 commit comments

Comments
 (0)