From 1380655601a469066a889c771b29d520004c0fc2 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 2 Mar 2021 14:35:13 -0800 Subject: [PATCH 001/109] Initialized sample --- .../project.pbxproj | 18 ++++++++ .../Content Display Logic/ContentPList.plist | 8 ++++ ...yContentUtilityNetworkContainer.storyboard | 45 ++++++++++++++++++ ...tilityNetworkContainerViewController.swift | 28 +++++++++++ .../README.md | 46 +++++++++++++++++++ .../README.metadata.json | 32 +++++++++++++ .../PerformValveIsolationTrace.storyboard | 4 +- 7 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index 9984f7611..cfc13f9e9 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -843,6 +843,9 @@ F16922B225158B1E00A8F36E /* EditKMLGroundOverlay.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F16922B125158B1E00A8F36E /* EditKMLGroundOverlay.storyboard */; }; F16922B525158B4400A8F36E /* EditKMLGroundOverlayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16922B425158B4400A8F36E /* EditKMLGroundOverlayViewController.swift */; }; F16922B7251590E200A8F36E /* EditKMLGroundOverlayViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F16922B425158B4400A8F36E /* EditKMLGroundOverlayViewController.swift */; }; + F1710AF025EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */; }; + F1710AF325EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */; }; + F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */; }; F17961A124DA3A27006FE7C1 /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1124F0B24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift */; }; F1987CFD23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; F1987CFF23F7321400DF41CC /* FindClosestFacilityInteractiveViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; @@ -938,6 +941,7 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( + F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */, 0023F98825E717EA006B574E /* SimulatedNMEADataSource.swift in CopyFiles */, 0023F98925E717EA006B574E /* DisplayDeviceLocationWithNMEADataSourcesViewController.swift in CopyFiles */, F1E8F0B32537D704000B9A0F /* NavigateRouteWithReroutingViewController.swift in CopyFiles */, @@ -1813,6 +1817,8 @@ F164997A22E924F40088CA93 /* EditAndSyncFeaturesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAndSyncFeaturesViewController.swift; sourceTree = ""; }; F16922B125158B1E00A8F36E /* EditKMLGroundOverlay.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = EditKMLGroundOverlay.storyboard; sourceTree = ""; }; F16922B425158B4400A8F36E /* EditKMLGroundOverlayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditKMLGroundOverlayViewController.swift; sourceTree = ""; }; + F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayContentUtilityNetworkContainerViewController.swift; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift"; sourceTree = SOURCE_ROOT; }; + F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = DisplayContentUtilityNetworkContainer.storyboard; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard"; sourceTree = SOURCE_ROOT; }; F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindClosestFacilityInteractiveViewController.swift; sourceTree = ""; }; F1987CFE23F7314000DF41CC /* FindClosestFacilityInteractive.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = FindClosestFacilityInteractive.storyboard; sourceTree = ""; }; F1987D0223F7677E00DF41CC /* DisplaySubtypeSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySubtypeSettingsViewController.swift; sourceTree = ""; }; @@ -4242,6 +4248,7 @@ D98CC08F22E25D8200618682 /* Utility network */ = { isa = PBXGroup; children = ( + F1710AEE25EECFB100900FF2 /* Display content of utility network container */, F14A8EFC2474AD3A00242D96 /* Configure subnetwork trace */, F1D50229245243AD00583CFB /* Display utility associations */, 00E5B7CB2458FE6D00B11973 /* Perform valve isolation trace */, @@ -4505,6 +4512,15 @@ path = "Edit KML ground overlay"; sourceTree = ""; }; + F1710AEE25EECFB100900FF2 /* Display content of utility network container */ = { + isa = PBXGroup; + children = ( + F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */, + F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */, + ); + path = "Display content of utility network container"; + sourceTree = ""; + }; F1A94D0F23F46FBF003E17B8 /* Find closest facility to an incident (interactive) */ = { isa = PBXGroup; children = ( @@ -4885,6 +4901,7 @@ C76F757421827C9C00938D8D /* ColorPicker.storyboard in Resources */, D97B7E621FD9BFE700E1239D /* Subdivisions.sbn in Resources */, 3ED028691B8E3A8500ACA70D /* SetViewpoint.storyboard in Resources */, + F1710AF325EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard in Resources */, 3EFCE1BD1CF36BC100E02F67 /* OpenMobileMapPackage.storyboard in Resources */, 9DF04DC02304C7F50014C1EE /* DownloadPreplannedMap.storyboard in Resources */, 166E8F9D1EE62E0E00C57C46 /* RasterLayer.storyboard in Resources */, @@ -5207,6 +5224,7 @@ 003BC31224E5E53200F65746 /* ConfigureSubnetworkTraceViewController.swift in Sources */, 3EEA06101D21C44000E03774 /* DisplaySceneViewController.swift in Sources */, 001D342F251BF94600F9EEBE /* ViewHiddenInfrastructureARExplorerViewController.swift in Sources */, + F1710AF025EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in Sources */, 4C0FD7CF22652E3B0042DE31 /* ReadSymbolsFromMobileStyleSymbolViewController.swift in Sources */, 10859BAC1FE0AAE400F6E552 /* FeatureLayerExtrusionViewController.swift in Sources */, C7FF07D621B9D258000D4055 /* FeatureLayerRenderingModeSceneViewController.swift in Sources */, diff --git a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist index 902e7d358..2e712fb07 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist +++ b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist @@ -1808,6 +1808,14 @@ displayName Configure subnetwork trace + + displayName + Display content of utility network container + storyboardName + DisplayContentUtilityNetworkContainer + descriptionText + A utility network container allows a dense collection of features to be represented by a single feature, which can be used to reduce map clutter. + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard new file mode 100644 index 000000000..0777940fd --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift new file mode 100644 index 000000000..b5fa0204e --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -0,0 +1,28 @@ +// Copyright 2021 Esri +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit +import ArcGIS + +class DisplayContentUtilityNetworkContainerViewController: UIViewController { + + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + // Add the source code button item to the right of navigation bar. + (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] + } +} diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md new file mode 100644 index 000000000..d8d60bb07 --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md @@ -0,0 +1,46 @@ +# Display content of utility network container + +A utility network container allows a dense collection of features to be represented by a single feature, which can be used to reduce map clutter. + +![Image of display content of utility network container](DisplayContentOfUtilityNetworkContainer.jpg) + +## Use case + +Offering a container view for features aids in the review for valid structural attachment and containment relationships and helps determine if a dataset has an association role set. Container views often model a cluster of electrical devices on a pole top or inside a cabinet or vault. + +## How to use the sample + +Tap on a container feature to show all features inside the container. The container is shown as a polygon graphic with the content features contained within. The viewpoint and scale of the map are also changed to the container's extent. Connectivity and Attachment associations inside the container are shown as dotted lines. + +## How it works + +1. Load a web map that include ArcGIS Pro [Subtype Group Layers](https://pro.arcgis.com/en/pro-app/help/mapping/layer-properties/subtype-layers.htm) with only container features visible (i.e. fuse bank, switch bank, transformer bank, hand hole and junction box). +2. Add a `GraphicsOverlay` for displaying a container view. +3. Create and load a `UtilityNetwork` with the same feature service URL as the layers in the `Map`. +4. Add an event handler for the `GeoViewTapped` event of the `MapView`. +5. Identify a feature and create a `UtilityElement` from it. +6. Get the associations for this element using `GetAssociationsAsync(UtilityElement, UtilityAssociationType.Containment)`. +7. Turn-off the visibility of all `OperationalLayers`. +8. Get the features for the `UtilityElement`(s) from the associations using `GetFeaturesForElementsAsync(IEnumerable)` +9. Add a `Graphic` with the same geometry and symbol as these features. +10. Add another `Graphic` that represents this extent and zoom to this extent with some buffer. +11. Get associations for this extent using `GetAssociationsAsync(Envelope)` +12. Add a `Graphic` to represent the association geometry between them using a symbol that distinguishes between `Attachment` and `Connectivity` association type. +13. Turn-on the visibility of all `OperationalLayers`, clear the `Graphics` and zoom out to previous extent to exit container view. + +## Relevant API + +* SubtypeFeatureLayer +* UtilityAssociation +* UtilityAssociationType +* UtilityElement +* UtilityNetwork +* UtilityNetworkDefinition + +## About the data + +The [Naperville electric network feature service](https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer), hosted on ArcGIS Online, contains a utility network used to find associations shown in this sample and a web map portal item, [naperville electric containers](https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef), that use the same feature service endpoint which displays only container features. + +## Tags + +associations, connectivity association, containment association, structural attachment associations, utility network diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json new file mode 100644 index 000000000..b718f998c --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json @@ -0,0 +1,32 @@ +{ + "category": "Utility network", + "description": "Create graphics for utility associations in a utility network.", + "ignore": false, + "images": [ + "display-utility-associations.png" + ], + "keywords": [ + "associating", + "association", + "attachment", + "connectivity", + "containment", + "relationships", + "AGSGraphicsOverlay", + "AGSUtilityAssociation", + "AGSUtilityAssociationType", + "AGSUtilityNetwork" + ], + "redirect_from": [ + ], + "relevant_apis": [ + "AGSGraphicsOverlay", + "AGSUtilityAssociation", + "AGSUtilityAssociationType", + "AGSUtilityNetwork" + ], + "snippets": [ + "DisplayUtilityAssociationsViewController.swift" + ], + "title": "Display utility associations" +} diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard index 80ed4937e..0b79a5def 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard @@ -1,9 +1,9 @@ - + - + From ee40734df86f7dd3540fb8ef4b171209f66de9f9 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 2 Mar 2021 18:47:59 -0800 Subject: [PATCH 002/109] Added button and most of source code --- ...yContentUtilityNetworkContainer.storyboard | 36 +++++++- ...tilityNetworkContainerViewController.swift | 92 ++++++++++++++++++- 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 0777940fd..4fdace73f 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -18,19 +18,51 @@ - + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index b5fa0204e..6f5086990 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -15,14 +15,104 @@ import UIKit import ArcGIS -class DisplayContentUtilityNetworkContainerViewController: UIViewController { +class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGSGeoViewTouchDelegate { + @IBOutlet var mapView: AGSMapView! { + didSet { + mapView.map = makeMap() + } + } + + let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! + var utilityNetwork: AGSUtilityNetwork? + var containerFeature: AGSArcGISFeature? + var previousViewpoint: AGSViewpoint? + let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) + let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) + let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) + func makeMap() -> AGSMap { + let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! + let map = AGSMap(url: webMapURL)! + return map + } // MARK: UIViewController override func viewDidLoad() { super.viewDidLoad() + + utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) + // Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] } + + func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { + mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { (layerResults, error) in + // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. + layerResults?.forEach { layerResult in + if self.containerFeature == nil, layerResult.layerContent is AGSSubtypeFeatureLayer { + layerResult.sublayerResults.forEach { sublayerResult in + sublayerResult.geoElements.forEach { geoElement in + if self.containerFeature == nil, let feature = geoElement as? AGSArcGISFeature { + self.containerFeature = feature + } + } + } + } + } + } + guard let containerFeature = containerFeature, let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } +// let containerElement = utilityNetwork?.createElement(with: containerFeature) + // Get the containment associations from this element to display its content. + utilityNetwork?.associations(with: containerElement, type: .containment) { [self] containmentAssociations, error in + var contentElements = [AGSUtilityElement]() + containmentAssociations?.forEach { association in + var otherElement: AGSUtilityElement + if association.fromElement.objectID == containerElement.objectID { + otherElement = association.toElement + } else { + otherElement = association.fromElement + } + contentElements.append(otherElement) + if contentElements.count > 0 { + previousViewpoint = self.mapView.currentViewpoint(with: .boundingGeometry) + (self.mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in + layer.isVisible = false + } + // Set container view visibility to visible. + + let overlay = mapView.graphicsOverlays[0] as? AGSGraphicsOverlay + utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in + contentFeatures?.forEach { content in + let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) + overlay?.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) + } + var boundingBox: AGSGeometry? + if overlay?.graphics.count == 1, (overlay?.graphics[0] as? AGSGraphic)?.geometry == mapPoint { + mapView.setViewpointCenter(mapPoint, scale: containerElement.assetType.containerViewScale) + boundingBox = mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry + } else { + boundingBox = AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05) + } + overlay?.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) + mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05)!) + + // Get the associations for this extent to display how content features are attached or connected. + utilityNetwork?.associations(withExtent: overlay!.extent) { (containmentAssociations, error) in + containmentAssociations?.forEach { association in + var symbol = AGSSymbol() + if association.associationType == .attachment { + symbol = attachmentSymbol + } else { + symbol = connectivitySymbol + } + overlay?.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + } + } + } + } + } + } + } } From a158e9d50650f5549febafc72f7779293771a2ab Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 4 Mar 2021 23:48:42 -0800 Subject: [PATCH 003/109] Reorganized code --- ...yContentUtilityNetworkContainer.storyboard | 35 ++--- ...tilityNetworkContainerViewController.swift | 127 +++++++++++------- 2 files changed, 93 insertions(+), 69 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 4fdace73f..76cf108ef 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -1,5 +1,5 @@ - + @@ -12,11 +12,16 @@ - + + @@ -25,24 +30,10 @@ - - - - - - - - - - - - - + + + + @@ -61,7 +52,9 @@ - + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 6f5086990..792476909 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -21,6 +21,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.map = makeMap() } } + @IBOutlet var containerView: UIView! + @IBOutlet var exitBarButtonItem: UIBarButtonItem! let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! var utilityNetwork: AGSUtilityNetwork? @@ -30,25 +32,54 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) + var map = AGSMap() func makeMap() -> AGSMap { let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! let map = AGSMap(url: webMapURL)! return map } + + @IBAction func exitContainerView() { + containerView.isHidden = true + containerFeature = nil + exitBarButtonItem.isEnabled = false + (mapView.graphicsOverlays[0] as? AGSGraphicsOverlay)?.graphics.removeAllObjects() + (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in + layer.isVisible = true + if let previousViewpoint = previousViewpoint { + mapView.setViewpoint(previousViewpoint) + } + } + } + + func loadUtilityNetwork() { + utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) + utilityNetwork?.load { [weak self] error in + guard let self = self else { return } + // Add self as the touch delegate for the map view. + self.mapView.touchDelegate = self + if let error = error { + self.presentAlert(error: error) + } + } + } // MARK: UIViewController override func viewDidLoad() { super.viewDidLoad() - - utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) - + loadUtilityNetwork() + mapView.graphicsOverlays.add(AGSGraphicsOverlay()) // Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] } func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { - mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { (layerResults, error) in + if !containerView.isHidden { + return + } + mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in + guard let self = self else { return } // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. layerResults?.forEach { layerResult in if self.containerFeature == nil, layerResult.layerContent is AGSSubtypeFeatureLayer { @@ -61,53 +92,53 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } } - } - guard let containerFeature = containerFeature, let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } -// let containerElement = utilityNetwork?.createElement(with: containerFeature) - // Get the containment associations from this element to display its content. - utilityNetwork?.associations(with: containerElement, type: .containment) { [self] containmentAssociations, error in - var contentElements = [AGSUtilityElement]() - containmentAssociations?.forEach { association in - var otherElement: AGSUtilityElement - if association.fromElement.objectID == containerElement.objectID { - otherElement = association.toElement - } else { - otherElement = association.fromElement - } - contentElements.append(otherElement) - if contentElements.count > 0 { - previousViewpoint = self.mapView.currentViewpoint(with: .boundingGeometry) - (self.mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in - layer.isVisible = false + guard let containerFeature = self.containerFeature, let containerElement = self.utilityNetwork?.createElement(with: containerFeature) else { return } + // Get the containment associations from this element to display its content. + self.utilityNetwork?.associations(with: containerElement, type: .containment) {containmentAssociations, error in + var contentElements = [AGSUtilityElement]() + containmentAssociations?.forEach { association in + var otherElement: AGSUtilityElement + if association.fromElement.objectID == containerElement.objectID { + otherElement = association.toElement + } else { + otherElement = association.fromElement } - // Set container view visibility to visible. - - let overlay = mapView.graphicsOverlays[0] as? AGSGraphicsOverlay - utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in - contentFeatures?.forEach { content in - let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) - overlay?.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) - } - var boundingBox: AGSGeometry? - if overlay?.graphics.count == 1, (overlay?.graphics[0] as? AGSGraphic)?.geometry == mapPoint { - mapView.setViewpointCenter(mapPoint, scale: containerElement.assetType.containerViewScale) - boundingBox = mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry - } else { - boundingBox = AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05) + contentElements.append(otherElement) + if !contentElements.isEmpty { + self.previousViewpoint = self.mapView.currentViewpoint(with: .boundingGeometry) + (self.mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in + layer.isVisible = false } - overlay?.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) - mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05)!) - - // Get the associations for this extent to display how content features are attached or connected. - utilityNetwork?.associations(withExtent: overlay!.extent) { (containmentAssociations, error) in - containmentAssociations?.forEach { association in - var symbol = AGSSymbol() - if association.associationType == .attachment { - symbol = attachmentSymbol - } else { - symbol = connectivitySymbol + // Set container view visibility to visible. + self.containerView.isHidden = false + let overlay = self.mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay + self.utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in + contentFeatures?.forEach { content in + let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) + overlay?.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) + } + var boundingBox: AGSGeometry? + if overlay?.graphics.count == 1, (overlay?.graphics[0] as? AGSGraphic)?.geometry == mapPoint { + self.mapView.setViewpointCenter(mapPoint, scale: containerElement.assetType.containerViewScale) + boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry + } else { + boundingBox = AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05) + } + overlay?.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) + self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05)!) + + // Get the associations for this extent to display how content features are attached or connected. + self.utilityNetwork?.associations(withExtent: overlay!.extent) { (containmentAssociations, error) in + containmentAssociations?.forEach { association in + var symbol = AGSSymbol() + if association.associationType == .attachment { + symbol = self.attachmentSymbol + } else { + symbol = self.connectivitySymbol + } + overlay?.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) } - overlay?.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + self.exitBarButtonItem.isEnabled = true } } } From 248aabd1da1718645def4ee09c997ee13f70ea8b Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 5 Mar 2021 16:25:57 -0800 Subject: [PATCH 004/109] Added error handling --- ...ContentUtilityNetworkContainerViewController.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 792476909..b2992439d 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -49,6 +49,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS layer.isVisible = true if let previousViewpoint = previousViewpoint { mapView.setViewpoint(previousViewpoint) + mapView.isUserInteractionEnabled = true } } } @@ -118,8 +119,10 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS overlay?.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } var boundingBox: AGSGeometry? - if overlay?.graphics.count == 1, (overlay?.graphics[0] as? AGSGraphic)?.geometry == mapPoint { - self.mapView.setViewpointCenter(mapPoint, scale: containerElement.assetType.containerViewScale) + if overlay?.graphics.count == 1, +// let point = (overlay?.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint + let point = (overlay?.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { + self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry } else { boundingBox = AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05) @@ -139,6 +142,10 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS overlay?.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) } self.exitBarButtonItem.isEnabled = true + self.mapView.isUserInteractionEnabled = false + if let error = error { + self.presentAlert(error: error) + } } } } From 74f65b0e17addb3778d22e43e2b3c4ff7731358b Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 9 Mar 2021 11:56:17 -0800 Subject: [PATCH 005/109] Guarded overlay and added legend BBi --- ...yContentUtilityNetworkContainer.storyboard | 2 ++ ...tilityNetworkContainerViewController.swift | 21 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 76cf108ef..76dbff961 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -29,6 +29,8 @@ + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index b2992439d..7ec7d370c 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -95,7 +95,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } guard let containerFeature = self.containerFeature, let containerElement = self.utilityNetwork?.createElement(with: containerFeature) else { return } // Get the containment associations from this element to display its content. - self.utilityNetwork?.associations(with: containerElement, type: .containment) {containmentAssociations, error in + self.utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in var contentElements = [AGSUtilityElement]() containmentAssociations?.forEach { association in var otherElement: AGSUtilityElement @@ -112,26 +112,25 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // Set container view visibility to visible. self.containerView.isHidden = false - let overlay = self.mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay + guard let overlay = self.mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } self.utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in contentFeatures?.forEach { content in let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) - overlay?.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) + overlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } var boundingBox: AGSGeometry? - if overlay?.graphics.count == 1, -// let point = (overlay?.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint - let point = (overlay?.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { + if overlay.graphics.count == 1, + let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry } else { - boundingBox = AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05) + boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) } - overlay?.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) - self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay!.extent, byDistance: 0.05)!) + overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) + self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) // Get the associations for this extent to display how content features are attached or connected. - self.utilityNetwork?.associations(withExtent: overlay!.extent) { (containmentAssociations, error) in + self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in containmentAssociations?.forEach { association in var symbol = AGSSymbol() if association.associationType == .attachment { @@ -139,7 +138,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } else { symbol = self.connectivitySymbol } - overlay?.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) } self.exitBarButtonItem.isEnabled = true self.mapView.isUserInteractionEnabled = false From cee5cc8db9410d8f5daecf3e5d247766bed4f369 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 9 Mar 2021 14:18:58 -0800 Subject: [PATCH 006/109] Added completion for setViewpoint --- ...DisplayContentUtilityNetworkContainerViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 7ec7d370c..085d89e79 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -121,8 +121,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS var boundingBox: AGSGeometry? if overlay.graphics.count == 1, let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { - self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) - boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry + self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in + boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry + } } else { boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) } From 9b79acbde087e33087d4ac2a39e8c887fc03f245 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 9 Mar 2021 14:30:49 -0800 Subject: [PATCH 007/109] Added table view controller --- .../project.pbxproj | 4 +++ ...yContentUtilityNetworkContainer.storyboard | 35 +++++++++++++++++-- ...entUtilityNetworkTableViewController.swift | 20 +++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index cfc13f9e9..258a0625b 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -847,6 +847,7 @@ F1710AF325EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */; }; F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */; }; F17961A124DA3A27006FE7C1 /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1124F0B24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift */; }; + F1841C6725F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */; }; F1987CFD23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; F1987CFF23F7321400DF41CC /* FindClosestFacilityInteractiveViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; F1987D0023F7325300DF41CC /* FindClosestFacilityInteractive.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1987CFE23F7314000DF41CC /* FindClosestFacilityInteractive.storyboard */; }; @@ -1819,6 +1820,7 @@ F16922B425158B4400A8F36E /* EditKMLGroundOverlayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditKMLGroundOverlayViewController.swift; sourceTree = ""; }; F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayContentUtilityNetworkContainerViewController.swift; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift"; sourceTree = SOURCE_ROOT; }; F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = DisplayContentUtilityNetworkContainer.storyboard; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard"; sourceTree = SOURCE_ROOT; }; + F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayContentUtilityNetworkTableViewController.swift; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift"; sourceTree = SOURCE_ROOT; }; F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindClosestFacilityInteractiveViewController.swift; sourceTree = ""; }; F1987CFE23F7314000DF41CC /* FindClosestFacilityInteractive.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = FindClosestFacilityInteractive.storyboard; sourceTree = ""; }; F1987D0223F7677E00DF41CC /* DisplaySubtypeSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySubtypeSettingsViewController.swift; sourceTree = ""; }; @@ -4516,6 +4518,7 @@ isa = PBXGroup; children = ( F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */, + F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */, F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */, ); path = "Display content of utility network container"; @@ -5217,6 +5220,7 @@ 3ED75D041ED39EDF009B1F75 /* FindServiceAreaInteractiveViewController.swift in Sources */, 3E4BF4441C5AEA6500D85919 /* WorldAddressesViewController.swift in Sources */, 9DE9FE3422FDB7CA00142DE1 /* LocationHistoryViewController.swift in Sources */, + F1841C6725F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift in Sources */, 3ED028EF1B8E3AA500ACA70D /* FeatureLayerSelectionViewController.swift in Sources */, 3E5E09401EF4567A00FF3454 /* RelatedFeaturesViewController.swift in Sources */, D97B7E3C1FD9BE2B00E1239D /* SymbolizeShapefileViewController.swift in Sources */, diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 76dbff961..818399b3c 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -23,11 +23,11 @@ - + - + @@ -57,12 +57,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift new file mode 100644 index 000000000..ca8b2599e --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -0,0 +1,20 @@ +// Copyright 2021 Esri +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit +import ArcGIS + +class DisplayContentUtilityNetworkTableViewController: UITableViewController { + +} From 2a07704c72ac0c73e19c9e9e7f91bff059d7cb9d Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 9 Mar 2021 18:22:17 -0800 Subject: [PATCH 008/109] Added get associations function --- ...tilityNetworkContainerViewController.swift | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 085d89e79..4b12affe5 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -65,6 +65,31 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } } + + func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { + overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) + self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) { _ in + // Get the associations for this extent to display how content features are attached or connected. + self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in + containmentAssociations?.forEach { association in + var symbol = AGSSymbol() + if association.associationType == .attachment { + symbol = self.attachmentSymbol + } else { + symbol = self.connectivitySymbol + } + overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + } + self.exitBarButtonItem.isEnabled = true + self.mapView.isUserInteractionEnabled = false + if let error = error { + self.presentAlert(error: error) + } + } + } + + } + // MARK: UIViewController override func viewDidLoad() { @@ -122,31 +147,34 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS if overlay.graphics.count == 1, let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in - boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry + guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } + self.getAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) +// boundingBox = boundingBox } } else { boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) + self.getAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) } - overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) - self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) - - // Get the associations for this extent to display how content features are attached or connected. - self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in - containmentAssociations?.forEach { association in - var symbol = AGSSymbol() - if association.associationType == .attachment { - symbol = self.attachmentSymbol - } else { - symbol = self.connectivitySymbol - } - overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) - } - self.exitBarButtonItem.isEnabled = true - self.mapView.isUserInteractionEnabled = false - if let error = error { - self.presentAlert(error: error) - } - } +// overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) +// self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) +// +// // Get the associations for this extent to display how content features are attached or connected. +// self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in +// containmentAssociations?.forEach { association in +// var symbol = AGSSymbol() +// if association.associationType == .attachment { +// symbol = self.attachmentSymbol +// } else { +// symbol = self.connectivitySymbol +// } +// overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) +// } +// self.exitBarButtonItem.isEnabled = true +// self.mapView.isUserInteractionEnabled = false +// if let error = error { +// self.presentAlert(error: error) +// } +// } } } } From e821ecbf56212646af1e75693df3d2e1323669be Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 10 Mar 2021 19:03:56 -0800 Subject: [PATCH 009/109] Added data source to table view controller --- ...yContentUtilityNetworkContainer.storyboard | 19 +++++---- ...tilityNetworkContainerViewController.swift | 39 ++++++++++++++++++- ...entUtilityNetworkTableViewController.swift | 8 ++++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 818399b3c..99df9717a 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -23,14 +23,20 @@ - + - + - + + + + + + + @@ -57,19 +63,16 @@ - - - - + - + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 4b12affe5..93d9744a2 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -15,7 +15,7 @@ import UIKit import ArcGIS -class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGSGeoViewTouchDelegate { +class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGSGeoViewTouchDelegate, UIAdaptivePresentationControllerDelegate { @IBOutlet var mapView: AGSMapView! { didSet { mapView.map = makeMap() @@ -28,11 +28,12 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS var utilityNetwork: AGSUtilityNetwork? var containerFeature: AGSArcGISFeature? var previousViewpoint: AGSViewpoint? + var legendInfos = [AGSLegendInfo]() let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) - var map = AGSMap() + func makeMap() -> AGSMap { let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! @@ -66,6 +67,23 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } + func getLegends() { + guard let featureTable = AGSServiceFeatureTable(url: featureServiceURL).item else { return } + let featureLayers = [ + AGSFeatureLayer(item: featureTable, layerID: 105), + AGSFeatureLayer(item: featureTable, layerID: 900) + ] + featureLayers.forEach { layer in + layer.fetchLegendInfos{ [weak self] legendInfos, error in + guard let self = self, let legendInfos = legendInfos else { return } + self.legendInfos = legendInfos + if let error = error { + self.presentAlert(error: error) + } + } + } + } + func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) { _ in @@ -181,4 +199,21 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } } + + // MARK: - Navigation + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "DisplayContentLegendSegue" { + let controller = segue.destination as! DisplayContentUtilityNetworkTableViewController + controller.presentationController?.delegate = self + controller.preferredContentSize = CGSize(width: 300, height: 200) + controller.legendInfos = legendInfos + } + } + + // MARK: - UIAdaptivePresentationControllerDelegate + + func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { + return UIModalPresentationStyle.none + } } diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift index ca8b2599e..d5e110747 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -16,5 +16,13 @@ import UIKit import ArcGIS class DisplayContentUtilityNetworkTableViewController: UITableViewController { + var legendInfos = [AGSLegendInfo]() + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + <#code#> + } + + override func numberOfSections(in tableView: UITableView) -> Int { + <#code#> + } } From 14fecb9f6c476156bb33b8ac212c1eb15a94b547 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 11 Mar 2021 19:16:28 -0800 Subject: [PATCH 010/109] Loaded legend with all symbols --- ...yContentUtilityNetworkContainer.storyboard | 6 +-- ...tilityNetworkContainerViewController.swift | 35 ++++++++++++---- ...entUtilityNetworkTableViewController.swift | 42 ++++++++++++++++++- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 99df9717a..ac2a308f9 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -32,7 +32,7 @@ - + @@ -73,12 +73,12 @@ - + - + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 93d9744a2..609cbea94 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -28,6 +28,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS var utilityNetwork: AGSUtilityNetwork? var containerFeature: AGSArcGISFeature? var previousViewpoint: AGSViewpoint? + var featureLayers = [AGSFeatureLayer]() var legendInfos = [AGSLegendInfo]() let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) @@ -68,15 +69,13 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } func getLegends() { - guard let featureTable = AGSServiceFeatureTable(url: featureServiceURL).item else { return } - let featureLayers = [ - AGSFeatureLayer(item: featureTable, layerID: 105), - AGSFeatureLayer(item: featureTable, layerID: 900) - ] + let electricDistributionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/105")!) + let structureJunctionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/900")!) + featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in - layer.fetchLegendInfos{ [weak self] legendInfos, error in + layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } - self.legendInfos = legendInfos + self.legendInfos.append(contentsOf: legendInfos) if let error = error { self.presentAlert(error: error) } @@ -114,6 +113,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS super.viewDidLoad() loadUtilityNetwork() mapView.graphicsOverlays.add(AGSGraphicsOverlay()) + getLegends() // Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] } @@ -208,6 +208,27 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS controller.presentationController?.delegate = self controller.preferredContentSize = CGSize(width: 300, height: 200) controller.legendInfos = legendInfos + boundingBoxSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + if let image = image { + controller.boundingBoxSwatch = image.withRenderingMode(.alwaysOriginal) + } else if let error = error { + self.presentAlert(error: error) + } + } + attachmentSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + if let image = image { + controller.attachmentSwatch = image.withRenderingMode(.alwaysOriginal) + } else if let error = error { + self.presentAlert(error: error) + } + } + connectivitySymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + if let image = image { + controller.connectivitySwatch = image.withRenderingMode(.alwaysOriginal) + } else if let error = error { + self.presentAlert(error: error) + } + } } } diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift index d5e110747..b84ec0abe 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -17,12 +17,50 @@ import ArcGIS class DisplayContentUtilityNetworkTableViewController: UITableViewController { var legendInfos = [AGSLegendInfo]() + var boundingBoxSwatch: UIImage? + var attachmentSwatch: UIImage? + var connectivitySwatch: UIImage? + var contentSwatchesDict = KeyValuePairs() + + func makeDictionary() -> KeyValuePairs { + if let boundingBoxSwatch = boundingBoxSwatch, let attachmentSwatch = attachmentSwatch, let connectivitySwatch = connectivitySwatch { + return [ + "Bounding box": boundingBoxSwatch, + "Attachment": attachmentSwatch, + "Connectivity": connectivitySwatch + ] + } + return [:] + } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - <#code#> + contentSwatchesDict = makeDictionary() + return legendInfos.count + contentSwatchesDict.count } override func numberOfSections(in tableView: UITableView) -> Int { - <#code#> + 1 + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayContentLegendCell", for: indexPath) + if indexPath.row >= legendInfos.count { + let contentSwatch = indexPath.row - legendInfos.count + cell.textLabel?.text = contentSwatchesDict[contentSwatch].key + cell.imageView?.image = contentSwatchesDict[contentSwatch].value + } else { + let legendInfo = legendInfos[indexPath.row] + cell.textLabel?.text = legendInfo.name + legendInfo.symbol?.createSwatch { (image, _) in + cell.imageView?.image = image + } + } + cell.setNeedsLayout() + return cell + } + + override func viewDidLoad() { + super.viewDidLoad() } } From b3ddc54a9e3376b7a8393c70ea952a499d39afef Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 11 Mar 2021 19:46:44 -0800 Subject: [PATCH 011/109] Turned off selection --- .../DisplayContentUtilityNetworkContainer.storyboard | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index ac2a308f9..9ebd5805a 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From 6aa21a00597ed0e6f202ed6f57f7ca634de24d81 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 12 Mar 2021 14:58:59 -0800 Subject: [PATCH 012/109] Moved update cells --- .../DisplayContentUtilityNetworkTableViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift index b84ec0abe..aba42d4e7 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -49,14 +49,15 @@ class DisplayContentUtilityNetworkTableViewController: UITableViewController { let contentSwatch = indexPath.row - legendInfos.count cell.textLabel?.text = contentSwatchesDict[contentSwatch].key cell.imageView?.image = contentSwatchesDict[contentSwatch].value + cell.setNeedsLayout() } else { let legendInfo = legendInfos[indexPath.row] cell.textLabel?.text = legendInfo.name legendInfo.symbol?.createSwatch { (image, _) in cell.imageView?.image = image + cell.setNeedsLayout() } } - cell.setNeedsLayout() return cell } From acb59482e3d776f69eb822bfec542e938e1d8648 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 15 Mar 2021 18:47:27 -0700 Subject: [PATCH 013/109] Split into functions --- ...tilityNetworkContainerViewController.swift | 157 +++++++++--------- 1 file changed, 80 insertions(+), 77 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 609cbea94..3e662509c 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -84,8 +84,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { - overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) - self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) { _ in + overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) + mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) { _ in // Get the associations for this extent to display how content features are attached or connected. self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in containmentAssociations?.forEach { association in @@ -96,15 +96,14 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS symbol = self.connectivitySymbol } overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + self.exitBarButtonItem.isEnabled = true + self.mapView.isUserInteractionEnabled = false } - self.exitBarButtonItem.isEnabled = true - self.mapView.isUserInteractionEnabled = false if let error = error { self.presentAlert(error: error) } } } - } // MARK: UIViewController @@ -118,84 +117,88 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] } - func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { - if !containerView.isHidden { - return - } - mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in - guard let self = self else { return } - // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. - layerResults?.forEach { layerResult in - if self.containerFeature == nil, layerResult.layerContent is AGSSubtypeFeatureLayer { - layerResult.sublayerResults.forEach { sublayerResult in - sublayerResult.geoElements.forEach { geoElement in - if self.containerFeature == nil, let feature = geoElement as? AGSArcGISFeature { - self.containerFeature = feature - } + func setContainerFeature(layerResults: [AGSIdentifyLayerResult]) { + // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. + layerResults.forEach { layerResult in + if self.containerFeature == nil, layerResult.layerContent is AGSSubtypeFeatureLayer { + layerResult.sublayerResults.forEach { sublayerResult in + sublayerResult.geoElements.forEach { geoElement in + if let feature = geoElement as? AGSArcGISFeature { + self.containerFeature = feature } } } } - guard let containerFeature = self.containerFeature, let containerElement = self.utilityNetwork?.createElement(with: containerFeature) else { return } - // Get the containment associations from this element to display its content. - self.utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in - var contentElements = [AGSUtilityElement]() - containmentAssociations?.forEach { association in - var otherElement: AGSUtilityElement - if association.fromElement.objectID == containerElement.objectID { - otherElement = association.toElement - } else { - otherElement = association.fromElement - } - contentElements.append(otherElement) - if !contentElements.isEmpty { - self.previousViewpoint = self.mapView.currentViewpoint(with: .boundingGeometry) - (self.mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in - layer.isVisible = false - } - // Set container view visibility to visible. - self.containerView.isHidden = false - guard let overlay = self.mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } - self.utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in - contentFeatures?.forEach { content in - let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) - overlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) - } - var boundingBox: AGSGeometry? - if overlay.graphics.count == 1, - let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { - self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in - guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } - self.getAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) -// boundingBox = boundingBox - } - } else { - boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) - self.getAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) - } -// overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: self.boundingBoxSymbol)) -// self.mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) -// -// // Get the associations for this extent to display how content features are attached or connected. -// self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in -// containmentAssociations?.forEach { association in -// var symbol = AGSSymbol() -// if association.associationType == .attachment { -// symbol = self.attachmentSymbol -// } else { -// symbol = self.connectivitySymbol -// } -// overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) -// } -// self.exitBarButtonItem.isEnabled = true -// self.mapView.isUserInteractionEnabled = false -// if let error = error { -// self.presentAlert(error: error) -// } -// } - } + } + } + + func displayGraphics(with containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { + previousViewpoint = mapView.currentViewpoint(with: .boundingGeometry) + (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in + layer.isVisible = false + } + // Set container view visibility to visible. + containerView.isHidden = false + guard let overlay = mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } + utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in + if let contentFeatures = contentFeatures { + contentFeatures.forEach { content in + let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) + overlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) + } + var boundingBox: AGSGeometry? + if overlay.graphics.count == 1, + let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { + self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in + guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } + self.getAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) + // boundingBox = boundingBox } + } else { + boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) + self.getAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) } + } else if let error = error { + self.presentAlert(error: error) + } + } + } + + func getAssociations() { + guard let containerFeature = containerFeature, let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } + // Get the containment associations from this element to display its content. + utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in + var contentElements = [AGSUtilityElement]() + containmentAssociations?.forEach { association in + var otherElement: AGSUtilityElement + if association.fromElement.objectID == containerElement.objectID { + otherElement = association.toElement + } else { + otherElement = association.fromElement + } + contentElements.append(otherElement) + + if !contentElements.isEmpty { + self.displayGraphics(with: containerElement, for: contentElements) + } + } + if let error = error { + self.presentAlert(error: error) + } + } + } + + func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { + if !containerView.isHidden { + return + } + mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in + guard let self = self else { return } + if let layerResults = layerResults { + self.setContainerFeature(layerResults: layerResults) + self.getAssociations() + } else if let error = error { + self.presentAlert(error: error) } } } From 4d42daa1cd4dec55e6b0e6a76922e58d4451d02a Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 16 Mar 2021 14:57:28 -0700 Subject: [PATCH 014/109] Fixed inconsistent behavior --- ...tUtilityNetworkContainerViewController.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 3e662509c..cb55e7e53 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -34,8 +34,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) - - + func makeMap() -> AGSMap { let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! let map = AGSMap(url: webMapURL)! @@ -85,7 +84,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) - mapView.setViewpointGeometry(AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)!) { _ in + let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! + mapView.setViewpointGeometry(geometry) { _ in // Get the associations for this extent to display how content features are attached or connected. self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in containmentAssociations?.forEach { association in @@ -96,9 +96,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS symbol = self.connectivitySymbol } overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) - self.exitBarButtonItem.isEnabled = true - self.mapView.isUserInteractionEnabled = false } + self.exitBarButtonItem.isEnabled = true + self.mapView.isUserInteractionEnabled = false if let error = error { self.presentAlert(error: error) } @@ -177,10 +177,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS otherElement = association.fromElement } contentElements.append(otherElement) - - if !contentElements.isEmpty { - self.displayGraphics(with: containerElement, for: contentElements) - } + } + if !contentElements.isEmpty { + self.displayGraphics(with: containerElement, for: contentElements) } if let error = error { self.presentAlert(error: error) From 796381d7908ba6c7278a77761c38c81d0c21069a Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 16 Mar 2021 17:32:49 -0700 Subject: [PATCH 015/109] Deleted container view and animated viewpoint change --- ...yContentUtilityNetworkContainer.storyboard | 6 - ...tilityNetworkContainerViewController.swift | 173 ++++++++++-------- 2 files changed, 99 insertions(+), 80 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 9ebd5805a..fb35e08f3 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -17,11 +17,6 @@ - @@ -60,7 +55,6 @@ - diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index cb55e7e53..dd9d4cfc9 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -16,62 +16,75 @@ import UIKit import ArcGIS class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGSGeoViewTouchDelegate, UIAdaptivePresentationControllerDelegate { + /// The map view managed by the view controller. @IBOutlet var mapView: AGSMapView! { didSet { mapView.map = makeMap() } } - @IBOutlet var containerView: UIView! + /// The bar button item to prompt return of the main view. @IBOutlet var exitBarButtonItem: UIBarButtonItem! + /// A feature service for an electric utility network in Naperville, Illinois. let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! var utilityNetwork: AGSUtilityNetwork? - var containerFeature: AGSArcGISFeature? + /// The default or previous viewpoint before entering the container view. var previousViewpoint: AGSViewpoint? - var featureLayers = [AGSFeatureLayer]() + /// An array containing information about the feature services' legends. var legendInfos = [AGSLegendInfo]() + // The symbols used to display the container view contents. let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) - - func makeMap() -> AGSMap { - let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! - let map = AGSMap(url: webMapURL)! - return map - } + /// The action that is prompted when exiting the container view. @IBAction func exitContainerView() { - containerView.isHidden = true - containerFeature = nil + // Disable the bar button item since container view will be exited. exitBarButtonItem.isEnabled = false + // Remove all the objects that were added onto the graphics overlay. (mapView.graphicsOverlays[0] as? AGSGraphicsOverlay)?.graphics.removeAllObjects() (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in + // Make each operational layer visible. layer.isVisible = true - if let previousViewpoint = previousViewpoint { - mapView.setViewpoint(previousViewpoint) - mapView.isUserInteractionEnabled = true + guard let previousViewpoint = previousViewpoint else { return } + // Return to the viewpoint before container view was entered. + mapView.setViewpointGeometry(previousViewpoint.targetGeometry) { [weak self] _ in + // Enable interaction on the map view. + self?.mapView.isUserInteractionEnabled = true } } } + /// Create a map. + /// + /// - Returns: An `AGSMap` object. + func makeMap() -> AGSMap { + let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! + let map = AGSMap(url: webMapURL)! + return map + } + + /// Create and load the utility network using the feature service URL. func loadUtilityNetwork() { utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) utilityNetwork?.load { [weak self] error in guard let self = self else { return } - // Add self as the touch delegate for the map view. - self.mapView.touchDelegate = self if let error = error { self.presentAlert(error: error) } } } + /// Get the legend information provided by the feature layers used in the utility network. func getLegends() { + // Create feature tables from URLs. let electricDistributionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/105")!) let structureJunctionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/900")!) - featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) + // Create feature layers using the feature tables. + let featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in + // Get the legend information of each layer. layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } self.legendInfos.append(contentsOf: legendInfos) @@ -82,6 +95,49 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } + /// Get the container feature that was tapped on. + /// + /// - Parameters: + /// - layerResults: The layer results identified by the touch delegate. + /// - completion: A closure to pass back the feature that was tapped on. + func getContainerFeature(layerResults: [AGSIdentifyLayerResult], completion: @escaping (AGSArcGISFeature) -> Void) { + // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. + layerResults.forEach { layerResult in + if layerResult.layerContent is AGSSubtypeFeatureLayer { + layerResult.sublayerResults.forEach { sublayerResult in + sublayerResult.geoElements.forEach { geoElement in + if let feature = geoElement as? AGSArcGISFeature { + completion(feature) + } + } + } + } + } + } + + func getAssociations(for containerFeature: AGSArcGISFeature) { + guard let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } + // Get the containment associations from this element to display its content. + utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in + var contentElements = [AGSUtilityElement]() + containmentAssociations?.forEach { association in + var otherElement: AGSUtilityElement + if association.fromElement.objectID == containerElement.objectID { + otherElement = association.toElement + } else { + otherElement = association.fromElement + } + contentElements.append(otherElement) + } + if !contentElements.isEmpty { + self.getFeatures(with: containerElement, for: contentElements) + } + if let error = error { + self.presentAlert(error: error) + } + } + } + func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! @@ -106,39 +162,12 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } - // MARK: UIViewController - override func viewDidLoad() { - super.viewDidLoad() - loadUtilityNetwork() - mapView.graphicsOverlays.add(AGSGraphicsOverlay()) - getLegends() - // Add the source code button item to the right of navigation bar. - (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] - } - - func setContainerFeature(layerResults: [AGSIdentifyLayerResult]) { - // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. - layerResults.forEach { layerResult in - if self.containerFeature == nil, layerResult.layerContent is AGSSubtypeFeatureLayer { - layerResult.sublayerResults.forEach { sublayerResult in - sublayerResult.geoElements.forEach { geoElement in - if let feature = geoElement as? AGSArcGISFeature { - self.containerFeature = feature - } - } - } - } - } - } - - func displayGraphics(with containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { + func getFeatures(with containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { previousViewpoint = mapView.currentViewpoint(with: .boundingGeometry) (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in layer.isVisible = false } - // Set container view visibility to visible. - containerView.isHidden = false guard let overlay = mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in if let contentFeatures = contentFeatures { @@ -152,7 +181,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } self.getAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) - // boundingBox = boundingBox } } else { boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) @@ -164,52 +192,47 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } - func getAssociations() { - guard let containerFeature = containerFeature, let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } - // Get the containment associations from this element to display its content. - utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in - var contentElements = [AGSUtilityElement]() - containmentAssociations?.forEach { association in - var otherElement: AGSUtilityElement - if association.fromElement.objectID == containerElement.objectID { - otherElement = association.toElement - } else { - otherElement = association.fromElement - } - contentElements.append(otherElement) - } - if !contentElements.isEmpty { - self.displayGraphics(with: containerElement, for: contentElements) - } - if let error = error { - self.presentAlert(error: error) - } - } - } - + // MARK: - AGSGeoViewTouchDelegate func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { - if !containerView.isHidden { - return - } mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } if let layerResults = layerResults { - self.setContainerFeature(layerResults: layerResults) - self.getAssociations() + self.getContainerFeature(layerResults: layerResults) { containerFeature in + self.getAssociations(for: containerFeature) + } +// self.getAssociations() } else if let error = error { self.presentAlert(error: error) } } } + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + // Load the utility network. + loadUtilityNetwork() + // Add a graphics overlay. + mapView.graphicsOverlays.add(AGSGraphicsOverlay()) + // Add self as the touch delegate for the map view. + mapView.touchDelegate = self + // Get the legends from the feature service. + getLegends() + // Add the source code button item to the right of navigation bar. + (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] + } + // MARK: - Navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "DisplayContentLegendSegue" { let controller = segue.destination as! DisplayContentUtilityNetworkTableViewController controller.presentationController?.delegate = self + // Set the size of the view controller. controller.preferredContentSize = CGSize(width: 300, height: 200) controller.legendInfos = legendInfos + // Create a swatch of the bounding box symbol. boundingBoxSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in if let image = image { controller.boundingBoxSwatch = image.withRenderingMode(.alwaysOriginal) @@ -217,6 +240,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS self.presentAlert(error: error) } } + // Create a swatch of the attachment symbol. attachmentSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in if let image = image { controller.attachmentSwatch = image.withRenderingMode(.alwaysOriginal) @@ -224,6 +248,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS self.presentAlert(error: error) } } + // Create a swatch of the connectivity symbol. connectivitySymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in if let image = image { controller.connectivitySwatch = image.withRenderingMode(.alwaysOriginal) From 793b3c81bb47af398f35608baf7f074252c4819d Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Wed, 17 Mar 2021 14:33:27 -0700 Subject: [PATCH 016/109] Show error if edit fails. --- .../RelatedFeaturesViewController.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift index f60d6322c..7514db5ac 100644 --- a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift @@ -130,15 +130,19 @@ class RelatedFeaturesViewController: UITableViewController { // show progress hud SVProgressHUD.show(withStatus: "Applying edits") - relatedTable.applyEdits { [weak self] (_, error) in + relatedTable.applyEdits { [weak self] (results, error) in SVProgressHUD.dismiss() - if let error = error { - // show error + if let firstResult = results?.first { + if firstResult.completedWithErrors { + // The edit fails with error. + self?.presentAlert(error: firstResult.error!) + } else { + // Query to update features in the table. + self?.queryRelatedFeatures() + } + } else if let error = error { self?.presentAlert(error: error) - } else { - // query to update features - self?.queryRelatedFeatures() } } } From e7fc18fec89a7309852eee2a23a35b23afe48645 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 17 Mar 2021 18:35:26 -0700 Subject: [PATCH 017/109] Added table view controller to project file --- arcgis-ios-sdk-samples.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index 258a0625b..40b4f9067 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -836,6 +836,7 @@ F15CF0C923EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15CF0C823EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift */; }; F15CF0CB23EE27F00038F052 /* DisplaySubtypeFeatureLayer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F15CF0CA23EE27F00038F052 /* DisplaySubtypeFeatureLayer.storyboard */; }; F15CF0CC23EE31A70038F052 /* DisplaySubtypeFeatureLayerViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F15CF0C823EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift */; }; + F16174B02602E55A00300FF9 /* DisplayContentUtilityNetworkTableViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */; }; F164997622E90F150088CA93 /* FeatureLayerDictionaryRendererViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1F62C4122E6560C00EFD599 /* FeatureLayerDictionaryRendererViewController.swift */; }; F164997922E924C40088CA93 /* EditAndSyncFeatures.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F164997822E924C40088CA93 /* EditAndSyncFeatures.storyboard */; }; F164997B22E924F40088CA93 /* EditAndSyncFeaturesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F164997A22E924F40088CA93 /* EditAndSyncFeaturesViewController.swift */; }; @@ -942,6 +943,7 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( + F16174B02602E55A00300FF9 /* DisplayContentUtilityNetworkTableViewController.swift in CopyFiles */, F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */, 0023F98825E717EA006B574E /* SimulatedNMEADataSource.swift in CopyFiles */, 0023F98925E717EA006B574E /* DisplayDeviceLocationWithNMEADataSourcesViewController.swift in CopyFiles */, From fd1f86a51555dcf4625b421739e36122a6a7de1c Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 17 Mar 2021 18:36:12 -0700 Subject: [PATCH 018/109] Added makeSwatch function --- ...tilityNetworkContainerViewController.swift | 152 +++++++++++------- ...entUtilityNetworkTableViewController.swift | 30 ++-- 2 files changed, 99 insertions(+), 83 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index dd9d4cfc9..cd78b7149 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -32,6 +32,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS var previousViewpoint: AGSViewpoint? /// An array containing information about the feature services' legends. var legendInfos = [AGSLegendInfo]() + var featureLayers = [AGSFeatureLayer]() // The symbols used to display the container view contents. let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) @@ -82,7 +83,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let electricDistributionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/105")!) let structureJunctionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/900")!) // Create feature layers using the feature tables. - let featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) + featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in // Get the legend information of each layer. layer.fetchLegendInfos { [weak self] (legendInfos, error) in @@ -115,11 +116,16 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } - func getAssociations(for containerFeature: AGSArcGISFeature) { + /// Get the containment associations from the chosen element. + /// + /// - Parameter containerFeature: The selected container feature + func getContainmentAssociations(for containerFeature: AGSArcGISFeature) { + // Create a container element using the selected feature. guard let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } // Get the containment associations from this element to display its content. utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in var contentElements = [AGSUtilityElement]() + // Determine the type of each element and add it to the array of content elements. containmentAssociations?.forEach { association in var otherElement: AGSUtilityElement if association.fromElement.objectID == containerElement.objectID { @@ -129,52 +135,39 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } contentElements.append(otherElement) } + // If there are elements, find their corresponding features. if !contentElements.isEmpty { - self.getFeatures(with: containerElement, for: contentElements) - } - if let error = error { + self.getFeatures(within: containerElement, for: contentElements) + } else if let error = error { self.presentAlert(error: error) } } } - func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { - overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) - let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! - mapView.setViewpointGeometry(geometry) { _ in - // Get the associations for this extent to display how content features are attached or connected. - self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in - containmentAssociations?.forEach { association in - var symbol = AGSSymbol() - if association.associationType == .attachment { - symbol = self.attachmentSymbol - } else { - symbol = self.connectivitySymbol - } - overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) - } - self.exitBarButtonItem.isEnabled = true - self.mapView.isUserInteractionEnabled = false - if let error = error { - self.presentAlert(error: error) - } - } - } - } - - - func getFeatures(with containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { + /// Get the features that correspond to the content's elements. + /// + /// - Parameters: + /// - containerElement: The container element of the selected feature + /// - contentElements: An array of the content elements. + func getFeatures(within containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { + // Save the previous viewpoint. previousViewpoint = mapView.currentViewpoint(with: .boundingGeometry) + // Hide the layers to display the container view. (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in layer.isVisible = false } + // Get the overlay to add the symbols to. guard let overlay = mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } - utilityNetwork?.features(for: contentElements) { (contentFeatures, error) in + // Get the corresponding features for the array of content elements. + utilityNetwork?.features(for: contentElements) { [weak self] (contentFeatures, error) in + guard let self = self else { return } if let contentFeatures = contentFeatures { + // Create and add a symbol for each of the features. contentFeatures.forEach { content in let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) overlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } + // The bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. var boundingBox: AGSGeometry? if overlay.graphics.count == 1, let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { @@ -192,35 +185,89 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } + /// Get associations for the specified extent and display its associations. + /// + /// - Parameters: + /// - boundingBox: The gemeotry which represents the boundaries of the extent. + /// - overlay: The overlay to add the symbols to. + func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { + // Add the bounding box symbol. + overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) + let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! + mapView.setViewpointGeometry(geometry) { _ in + // Get the associations for this extent to display how content features are attached or connected. + self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in + containmentAssociations?.forEach { association in + var symbol = AGSSymbol() + if association.associationType == .attachment { + symbol = self.attachmentSymbol + } else { + symbol = self.connectivitySymbol + } + overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + } + // Enable the bar button item to exit the container view. + self.exitBarButtonItem.isEnabled = true + // Turn off user interaction to avoid straying away from the container view. + self.mapView.isUserInteractionEnabled = false + if let error = error { + self.presentAlert(error: error) + } + } + } + } + // MARK: - AGSGeoViewTouchDelegate func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { + // Identify the top most feature that corresponds to the tapped point. mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } if let layerResults = layerResults { self.getContainerFeature(layerResults: layerResults) { containerFeature in - self.getAssociations(for: containerFeature) + self.getContainmentAssociations(for: containerFeature) } -// self.getAssociations() } else if let error = error { self.presentAlert(error: error) } } } - // MARK: UIViewController + /// Create a swatch from the provided symbol. + /// + /// - Parameter symbol: The symbol to make a swatch from. + /// - Returns The resulting image that represents the swatch. + func makeSwatch(symbol: AGSSymbol) -> UIImage { + let swatchGroup = DispatchGroup() + var swatchImage = UIImage() + swatchGroup.enter() + DispatchQueue.global(qos: .userInitiated).async { + symbol.createSwatch(withBackgroundColor: nil, screen: .main) { [weak self] (image, error) in + if let image = image { + swatchImage = image + } else if let error = error { + self?.presentAlert(error: error) + } + swatchGroup.leave() + } + } + swatchGroup.wait() + return swatchImage + } + + // MARK: - UIViewController override func viewDidLoad() { super.viewDidLoad() // Load the utility network. loadUtilityNetwork() - // Add a graphics overlay. - mapView.graphicsOverlays.add(AGSGraphicsOverlay()) // Add self as the touch delegate for the map view. mapView.touchDelegate = self + // Add a graphics overlay. + mapView.graphicsOverlays.add(AGSGraphicsOverlay()) // Get the legends from the feature service. getLegends() // Add the source code button item to the right of navigation bar. - (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainer"] + (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainerViewController", "DisplayContentUtilityNetworkTableViewController"] } // MARK: - Navigation @@ -232,30 +279,11 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Set the size of the view controller. controller.preferredContentSize = CGSize(width: 300, height: 200) controller.legendInfos = legendInfos - // Create a swatch of the bounding box symbol. - boundingBoxSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in - if let image = image { - controller.boundingBoxSwatch = image.withRenderingMode(.alwaysOriginal) - } else if let error = error { - self.presentAlert(error: error) - } - } - // Create a swatch of the attachment symbol. - attachmentSymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in - if let image = image { - controller.attachmentSwatch = image.withRenderingMode(.alwaysOriginal) - } else if let error = error { - self.presentAlert(error: error) - } - } - // Create a swatch of the connectivity symbol. - connectivitySymbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in - if let image = image { - controller.connectivitySwatch = image.withRenderingMode(.alwaysOriginal) - } else if let error = error { - self.presentAlert(error: error) - } - } + controller.contentSwatches = [ + "Bounding box": makeSwatch(symbol: boundingBoxSymbol), + "Attachment": makeSwatch(symbol: attachmentSymbol), + "Connectivity": makeSwatch(symbol: connectivitySymbol) + ] } } diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift index aba42d4e7..0a8d6cfc0 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -17,40 +17,28 @@ import ArcGIS class DisplayContentUtilityNetworkTableViewController: UITableViewController { var legendInfos = [AGSLegendInfo]() - var boundingBoxSwatch: UIImage? - var attachmentSwatch: UIImage? - var connectivitySwatch: UIImage? - var contentSwatchesDict = KeyValuePairs() - - func makeDictionary() -> KeyValuePairs { - if let boundingBoxSwatch = boundingBoxSwatch, let attachmentSwatch = attachmentSwatch, let connectivitySwatch = connectivitySwatch { - return [ - "Bounding box": boundingBoxSwatch, - "Attachment": attachmentSwatch, - "Connectivity": connectivitySwatch - ] - } - return [:] - } - + var contentSwatches = KeyValuePairs() + + // Set the number of rows. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - contentSwatchesDict = makeDictionary() - return legendInfos.count + contentSwatchesDict.count + return legendInfos.count + contentSwatches.count } + // Set the number of sections. override func numberOfSections(in tableView: UITableView) -> Int { 1 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayContentLegendCell", for: indexPath) + // Add the container view swatches to the legend after the feature layer legend information. if indexPath.row >= legendInfos.count { let contentSwatch = indexPath.row - legendInfos.count - cell.textLabel?.text = contentSwatchesDict[contentSwatch].key - cell.imageView?.image = contentSwatchesDict[contentSwatch].value + cell.textLabel?.text = contentSwatches[contentSwatch].key + cell.imageView?.image = contentSwatches[contentSwatch].value cell.setNeedsLayout() } else { + // Add the information provided by the feature layers to the legend. let legendInfo = legendInfos[indexPath.row] cell.textLabel?.text = legendInfo.name legendInfo.symbol?.createSwatch { (image, _) in From 69461dc250713db1a7f5648b56206b744a6200c0 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 17 Mar 2021 18:46:52 -0700 Subject: [PATCH 019/109] Updated image, readme, json --- .../README.md | 44 +++++++++--------- .../README.metadata.json | 32 +++++++------ .../display-content-utility-network.png | Bin 0 -> 70036 bytes 3 files changed, 40 insertions(+), 36 deletions(-) create mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/display-content-utility-network.png diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md index d8d60bb07..50e5f0592 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md @@ -2,7 +2,7 @@ A utility network container allows a dense collection of features to be represented by a single feature, which can be used to reduce map clutter. -![Image of display content of utility network container](DisplayContentOfUtilityNetworkContainer.jpg) +![Image of display content of utility network container](display-content-utility-network.png) ## Use case @@ -10,36 +10,36 @@ Offering a container view for features aids in the review for valid structural a ## How to use the sample -Tap on a container feature to show all features inside the container. The container is shown as a polygon graphic with the content features contained within. The viewpoint and scale of the map are also changed to the container's extent. Connectivity and Attachment associations inside the container are shown as dotted lines. +Tap on a container feature to show all features inside the container. The container is shown as a polygon graphic with the content features contained within. The viewpoint and scale of the map are also changed to the container's extent. Connectivity and attachment associations inside the container are shown as dotted lines. ## How it works -1. Load a web map that include ArcGIS Pro [Subtype Group Layers](https://pro.arcgis.com/en/pro-app/help/mapping/layer-properties/subtype-layers.htm) with only container features visible (i.e. fuse bank, switch bank, transformer bank, hand hole and junction box). -2. Add a `GraphicsOverlay` for displaying a container view. -3. Create and load a `UtilityNetwork` with the same feature service URL as the layers in the `Map`. -4. Add an event handler for the `GeoViewTapped` event of the `MapView`. -5. Identify a feature and create a `UtilityElement` from it. -6. Get the associations for this element using `GetAssociationsAsync(UtilityElement, UtilityAssociationType.Containment)`. -7. Turn-off the visibility of all `OperationalLayers`. -8. Get the features for the `UtilityElement`(s) from the associations using `GetFeaturesForElementsAsync(IEnumerable)` -9. Add a `Graphic` with the same geometry and symbol as these features. -10. Add another `Graphic` that represents this extent and zoom to this extent with some buffer. -11. Get associations for this extent using `GetAssociationsAsync(Envelope)` -12. Add a `Graphic` to represent the association geometry between them using a symbol that distinguishes between `Attachment` and `Connectivity` association type. -13. Turn-on the visibility of all `OperationalLayers`, clear the `Graphics` and zoom out to previous extent to exit container view. +1. Load a web map that includes ArcGIS Pro [Subtype Group Layers](https://pro.arcgis.com/en/pro-app/help/mapping/layer-properties/subtype-layers.htm) with only container features visible (i.e. fuse bank, switch bank, transformer bank, hand hole and junction box). +2. Create an `AGSMapView` and listen for `didTap` events on the `AGSGeoViewTouchDelegate`. +3. Create and load an `AGSUtilityNetwork`. +4. Add an `AGSGraphicsOverlay` for displaying a container view. +5. Identify the tapped feature and create an `AGSUtilityElement` from it. +6. Get the associations for this element using `AGSUtilityNetwork.associations(with:completion:)`. +7. Turn-off the visibility of all of the map's `operationalLayers`. +8. Get the features for the `AGSUtilityElement`(s) from the associations using `AGSUtilityNetwork.features(for:completion:)` +9. Add an `AGSGraphic` with the same geometry and symbol as these features. +10. Add another `AGSGraphic` that represents this extent and zoom to this extent with some buffer. +11. Get associations for this extent using `AGSUtilityNetwork.associations(withExtent:completion:)` +12. Add an `AGSGraphic` to represent the association geometry between them using a symbol that distinguishes between `attachment` and `connectivity` association type. +13. Turn-on the visibility of all `operationalLayers`, clear the `AGSGraphics` and zoom out to previous extent to exit container view. ## Relevant API -* SubtypeFeatureLayer -* UtilityAssociation -* UtilityAssociationType -* UtilityElement -* UtilityNetwork -* UtilityNetworkDefinition +* AGSSubtypeFeatureLayer +* AGSUtilityAssociation +* AGSUtilityAssociationType +* AGSUtilityElement +* AGSUtilityNetwork +* AGSUtilityNetworkDefinition ## About the data -The [Naperville electric network feature service](https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer), hosted on ArcGIS Online, contains a utility network used to find associations shown in this sample and a web map portal item, [naperville electric containers](https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef), that use the same feature service endpoint which displays only container features. +The [Naperville electric network feature service](https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer), hosted on ArcGIS Online, contains a utility network used to find associations shown in this sample and a web map portal item, [Naperville electric containers](https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef), that use the same feature service endpoint which displays only container features. ## Tags diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json index b718f998c..16e9e4b48 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json @@ -1,32 +1,36 @@ { "category": "Utility network", - "description": "Create graphics for utility associations in a utility network.", + "description": "A utility network container allows a dense collection of features to be represented by a single feature, which can be used to reduce map clutter.", "ignore": false, "images": [ - "display-utility-associations.png" + "display-content-utility-network.png" ], "keywords": [ - "associating", - "association", - "attachment", - "connectivity", - "containment", - "relationships", - "AGSGraphicsOverlay", + "associations", + "connectivity association", + "containment association", + "structural attachment associations", + "utility network", + "AGSSubtypeFeatureLayer", "AGSUtilityAssociation", "AGSUtilityAssociationType", - "AGSUtilityNetwork" + "AGSUtilityElement", + "AGSUtilityNetwork", + "AGSUtilityNetworkDefinition" ], "redirect_from": [ ], "relevant_apis": [ - "AGSGraphicsOverlay", + "AGSSubtypeFeatureLayer", "AGSUtilityAssociation", "AGSUtilityAssociationType", - "AGSUtilityNetwork" + "AGSUtilityElement", + "AGSUtilityNetwork", + "AGSUtilityNetworkDefinition" ], "snippets": [ - "DisplayUtilityAssociationsViewController.swift" + "DisplayContentUtilityNetworkContainerViewController.swift", + "DisplayContentUtilityNetworkTableViewController.swift" ], - "title": "Display utility associations" + "title": "Display content of utility network container" } diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/display-content-utility-network.png b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/display-content-utility-network.png new file mode 100644 index 0000000000000000000000000000000000000000..15f69bf8defe58bd34df336a6a8f290234091bdc GIT binary patch literal 70036 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 literal 0 HcmV?d00001 From 791b3f8e12d65004d72c4685fda66a0c5ebce287 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 17 Mar 2021 18:49:45 -0700 Subject: [PATCH 020/109] Added guard --- ...layContentUtilityNetworkContainerViewController.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index cd78b7149..75b4e9419 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -70,9 +70,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS func loadUtilityNetwork() { utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) utilityNetwork?.load { [weak self] error in - guard let self = self else { return } if let error = error { - self.presentAlert(error: error) + self?.presentAlert(error: error) } } } @@ -123,7 +122,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Create a container element using the selected feature. guard let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } // Get the containment associations from this element to display its content. - utilityNetwork?.associations(with: containerElement, type: .containment) { containmentAssociations, error in + utilityNetwork?.associations(with: containerElement, type: .containment) { [weak self] containmentAssociations, error in + guard let self = self else { return } var contentElements = [AGSUtilityElement]() // Determine the type of each element and add it to the array of content elements. containmentAssociations?.forEach { association in @@ -194,7 +194,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Add the bounding box symbol. overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! - mapView.setViewpointGeometry(geometry) { _ in + mapView.setViewpointGeometry(geometry) { [weak self] _ in + guard let self = self else { return } // Get the associations for this extent to display how content features are attached or connected. self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in containmentAssociations?.forEach { association in From 35e01c1581633b326459590c8eb93ba93a4c59be Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 17 Mar 2021 18:53:23 -0700 Subject: [PATCH 021/109] Reverted performa valve changes --- .../PerformValveIsolationTrace.storyboard | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard index 0b79a5def..80ed4937e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTrace.storyboard @@ -1,9 +1,9 @@ - + - + From c4a411ad62521a020c8afa3173f2a265cc9f8e1d Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Thu, 18 Mar 2021 16:39:25 -0700 Subject: [PATCH 022/109] Adjust the logic. --- .../RelatedFeaturesViewController.swift | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift index 7514db5ac..da9af021c 100644 --- a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift @@ -132,15 +132,14 @@ class RelatedFeaturesViewController: UITableViewController { relatedTable.applyEdits { [weak self] (results, error) in SVProgressHUD.dismiss() - - if let firstResult = results?.first { - if firstResult.completedWithErrors { + if let results = results { + if let firstResult = results.first, + firstResult.completedWithErrors { // The edit fails with error. self?.presentAlert(error: firstResult.error!) - } else { - // Query to update features in the table. - self?.queryRelatedFeatures() } + // Query to update features in the table. + self?.queryRelatedFeatures() } else if let error = error { self?.presentAlert(error: error) } From c28562a1dd722ec0c2f524454a2934c62fc1fe04 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Thu, 18 Mar 2021 16:56:29 -0700 Subject: [PATCH 023/109] Unwrap self with guard. --- .../RelatedFeaturesViewController.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift index da9af021c..9cc788f97 100644 --- a/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Add delete related features/RelatedFeaturesViewController.swift @@ -132,16 +132,17 @@ class RelatedFeaturesViewController: UITableViewController { relatedTable.applyEdits { [weak self] (results, error) in SVProgressHUD.dismiss() + guard let self = self else { return } if let results = results { if let firstResult = results.first, firstResult.completedWithErrors { // The edit fails with error. - self?.presentAlert(error: firstResult.error!) + self.presentAlert(error: firstResult.error!) } // Query to update features in the table. - self?.queryRelatedFeatures() + self.queryRelatedFeatures() } else if let error = error { - self?.presentAlert(error: error) + self.presentAlert(error: error) } } } From bdc3b0663ebb00ee7f98065b2061de7fa93cd619 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 19 Mar 2021 12:55:59 -0700 Subject: [PATCH 024/109] Addressed Friday review suggestions --- ...tilityNetworkContainerViewController.swift | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 75b4e9419..4120c1a9a 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -36,7 +36,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // The symbols used to display the container view contents. let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) - let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .blue, width: 3) + let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .green, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) /// The action that is prompted when exiting the container view. @@ -102,16 +102,10 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// - completion: A closure to pass back the feature that was tapped on. func getContainerFeature(layerResults: [AGSIdentifyLayerResult], completion: @escaping (AGSArcGISFeature) -> Void) { // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. - layerResults.forEach { layerResult in - if layerResult.layerContent is AGSSubtypeFeatureLayer { - layerResult.sublayerResults.forEach { sublayerResult in - sublayerResult.geoElements.forEach { geoElement in - if let feature = geoElement as? AGSArcGISFeature { - completion(feature) - } - } - } - } + let layerResult = layerResults.first(where: { $0.layerContent is AGSSubtypeFeatureLayer }) + layerResult?.sublayerResults.forEach { sublayerResult in + guard let feature = sublayerResult.geoElements.first(where: { $0 is AGSArcGISFeature }) as? AGSArcGISFeature else { return } + completion(feature) } } @@ -198,7 +192,11 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS guard let self = self else { return } // Get the associations for this extent to display how content features are attached or connected. self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in - containmentAssociations?.forEach { association in + guard let containmentAssociations = containmentAssociations else { return } + if containmentAssociations.isEmpty { + self.presentAlert(title: nil, message: "This feature contains no associations.") + } + containmentAssociations.forEach { association in var symbol = AGSSymbol() if association.associationType == .attachment { symbol = self.attachmentSymbol From acd345957007c14e05c801f0d66a5fff949af5eb Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 22 Mar 2021 14:18:39 -0700 Subject: [PATCH 025/109] Set viewpoint --- .../DisplayContentUtilityNetworkContainerViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 4120c1a9a..8bd4c8e2b 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -263,6 +263,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.touchDelegate = self // Add a graphics overlay. mapView.graphicsOverlays.add(AGSGraphicsOverlay()) + mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) // Get the legends from the feature service. getLegends() // Add the source code button item to the right of navigation bar. From d6fa19d4922643e261966d6cb5490ba74cdad8a9 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 24 Mar 2021 16:25:47 -0700 Subject: [PATCH 026/109] Renamed functions --- ...tilityNetworkContainerViewController.swift | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 8bd4c8e2b..2ef93a851 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -77,7 +77,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } /// Get the legend information provided by the feature layers used in the utility network. - func getLegends() { + func fetchLegendInfo() { // Create feature tables from URLs. let electricDistributionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/105")!) let structureJunctionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/900")!) @@ -100,7 +100,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// - Parameters: /// - layerResults: The layer results identified by the touch delegate. /// - completion: A closure to pass back the feature that was tapped on. - func getContainerFeature(layerResults: [AGSIdentifyLayerResult], completion: @escaping (AGSArcGISFeature) -> Void) { + func identifyContainerFeature(layerResults: [AGSIdentifyLayerResult], completion: @escaping (AGSArcGISFeature) -> Void) { // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. let layerResult = layerResults.first(where: { $0.layerContent is AGSSubtypeFeatureLayer }) layerResult?.sublayerResults.forEach { sublayerResult in @@ -112,7 +112,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// Get the containment associations from the chosen element. /// /// - Parameter containerFeature: The selected container feature - func getContainmentAssociations(for containerFeature: AGSArcGISFeature) { + func addElementAssociations(for containerFeature: AGSArcGISFeature) { // Create a container element using the selected feature. guard let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } // Get the containment associations from this element to display its content. @@ -121,29 +121,29 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS var contentElements = [AGSUtilityElement]() // Determine the type of each element and add it to the array of content elements. containmentAssociations?.forEach { association in - var otherElement: AGSUtilityElement + var element: AGSUtilityElement if association.fromElement.objectID == containerElement.objectID { - otherElement = association.toElement + element = association.toElement } else { - otherElement = association.fromElement + element = association.fromElement } - contentElements.append(otherElement) + contentElements.append(element) } // If there are elements, find their corresponding features. if !contentElements.isEmpty { - self.getFeatures(within: containerElement, for: contentElements) + self.addGraphicsToFeatures(within: containerElement, for: contentElements) } else if let error = error { self.presentAlert(error: error) } } } - /// Get the features that correspond to the content's elements. + /// Get the features that correspond to the content's elements and add graphics. /// /// - Parameters: /// - containerElement: The container element of the selected feature /// - contentElements: An array of the content elements. - func getFeatures(within containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { + func addGraphicsToFeatures(within containerElement: AGSUtilityElement, for contentElements: [AGSUtilityElement]) { // Save the previous viewpoint. previousViewpoint = mapView.currentViewpoint(with: .boundingGeometry) // Hide the layers to display the container view. @@ -167,11 +167,11 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } - self.getAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) + self.identifyAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) } } else { boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) - self.getAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) + self.identifyAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) } } else if let error = error { self.presentAlert(error: error) @@ -184,7 +184,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// - Parameters: /// - boundingBox: The gemeotry which represents the boundaries of the extent. /// - overlay: The overlay to add the symbols to. - func getAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { + func identifyAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { // Add the bounding box symbol. overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! @@ -222,8 +222,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } if let layerResults = layerResults { - self.getContainerFeature(layerResults: layerResults) { containerFeature in - self.getContainmentAssociations(for: containerFeature) + self.identifyContainerFeature(layerResults: layerResults) { containerFeature in + self.addElementAssociations(for: containerFeature) } } else if let error = error { self.presentAlert(error: error) @@ -265,7 +265,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.graphicsOverlays.add(AGSGraphicsOverlay()) mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) // Get the legends from the feature service. - getLegends() + fetchLegendInfo() // Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainerViewController", "DisplayContentUtilityNetworkTableViewController"] } From 954ad9f42815ed93dd62b001fd543283895309ce Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 24 Mar 2021 16:32:58 -0700 Subject: [PATCH 027/109] Update arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json Co-authored-by: Ting Chen --- .../README.metadata.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json index 16e9e4b48..a0ed6e36e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json @@ -18,8 +18,7 @@ "AGSUtilityNetwork", "AGSUtilityNetworkDefinition" ], - "redirect_from": [ - ], + "redirect_from": [], "relevant_apis": [ "AGSSubtypeFeatureLayer", "AGSUtilityAssociation", From 836f3aab1267e19f322b34ab99c9dac4a7096d10 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 24 Mar 2021 16:33:56 -0700 Subject: [PATCH 028/109] Update arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift Co-authored-by: Ting Chen --- .../DisplayContentUtilityNetworkContainerViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 2ef93a851..15c642a1b 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -290,6 +290,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // MARK: - UIAdaptivePresentationControllerDelegate func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { - return UIModalPresentationStyle.none + return .none } } From f3feb400a18383b1a11baaaad1940817b1caea88 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 24 Mar 2021 18:44:49 -0700 Subject: [PATCH 029/109] Addressed review comments --- ...yContentUtilityNetworkContainer.storyboard | 9 ++-- ...tilityNetworkContainerViewController.swift | 51 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index fb35e08f3..6fa83bb67 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -19,13 +19,12 @@ - - + @@ -43,7 +42,7 @@ - + @@ -56,6 +55,7 @@ + @@ -96,5 +96,8 @@ + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 15c642a1b..2cd42d696 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -24,10 +24,12 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } /// The bar button item to prompt return of the main view. @IBOutlet var exitBarButtonItem: UIBarButtonItem! + @IBOutlet var legendBarButtonItem: UIBarButtonItem! /// A feature service for an electric utility network in Naperville, Illinois. let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! var utilityNetwork: AGSUtilityNetwork? + let graphicsOverlay = AGSGraphicsOverlay() /// The default or previous viewpoint before entering the container view. var previousViewpoint: AGSViewpoint? /// An array containing information about the feature services' legends. @@ -44,7 +46,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Disable the bar button item since container view will be exited. exitBarButtonItem.isEnabled = false // Remove all the objects that were added onto the graphics overlay. - (mapView.graphicsOverlays[0] as? AGSGraphicsOverlay)?.graphics.removeAllObjects() + graphicsOverlay.graphics.removeAllObjects() (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in // Make each operational layer visible. layer.isVisible = true @@ -70,6 +72,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS func loadUtilityNetwork() { utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) utilityNetwork?.load { [weak self] error in + // Add self as the touch delegate for the map view. + self?.mapView.touchDelegate = self if let error = error { self?.presentAlert(error: error) } @@ -79,14 +83,15 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// Get the legend information provided by the feature layers used in the utility network. func fetchLegendInfo() { // Create feature tables from URLs. - let electricDistributionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/105")!) - let structureJunctionTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer/900")!) + let electricDistributionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("105")) + let structureJunctionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("900")) // Create feature layers using the feature tables. featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in // Get the legend information of each layer. layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } + self.legendBarButtonItem.isEnabled = true self.legendInfos.append(contentsOf: legendInfos) if let error = error { self.presentAlert(error: error) @@ -150,28 +155,29 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in layer.isVisible = false } - // Get the overlay to add the symbols to. - guard let overlay = mapView.graphicsOverlays.firstObject as? AGSGraphicsOverlay else { return } // Get the corresponding features for the array of content elements. utilityNetwork?.features(for: contentElements) { [weak self] (contentFeatures, error) in guard let self = self else { return } if let contentFeatures = contentFeatures { + if contentFeatures.count == 1 { + self.presentAlert(title: nil, message: "This feature contains no associations.") + } // Create and add a symbol for each of the features. contentFeatures.forEach { content in let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) - overlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) + self.graphicsOverlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } // The bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. var boundingBox: AGSGeometry? - if overlay.graphics.count == 1, - let point = (overlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { + if self.graphicsOverlay.graphics.count == 1, + let point = (self.graphicsOverlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } - self.identifyAssociationsWithExtent(boundingBox: boundingBox, overlay: overlay) + self.identifyAssociationsWithExtent(boundingBox: boundingBox) } } else { - boundingBox = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05) - self.identifyAssociationsWithExtent(boundingBox: boundingBox!, overlay: overlay) + boundingBox = AGSGeometryEngine.bufferGeometry(self.graphicsOverlay.extent, byDistance: 0.05) + self.identifyAssociationsWithExtent(boundingBox: boundingBox!) } } else if let error = error { self.presentAlert(error: error) @@ -181,21 +187,16 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// Get associations for the specified extent and display its associations. /// - /// - Parameters: - /// - boundingBox: The gemeotry which represents the boundaries of the extent. - /// - overlay: The overlay to add the symbols to. - func identifyAssociationsWithExtent(boundingBox: AGSGeometry, overlay: AGSGraphicsOverlay) { + /// - Parameter boundingBox: The gemeotry which represents the boundaries of the extent. + func identifyAssociationsWithExtent(boundingBox: AGSGeometry) { // Add the bounding box symbol. - overlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) - let geometry = AGSGeometryEngine.bufferGeometry(overlay.extent, byDistance: 0.05)! + graphicsOverlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) + let geometry = AGSGeometryEngine.bufferGeometry(graphicsOverlay.extent, byDistance: 0.05)! mapView.setViewpointGeometry(geometry) { [weak self] _ in guard let self = self else { return } // Get the associations for this extent to display how content features are attached or connected. - self.utilityNetwork?.associations(withExtent: overlay.extent) { (containmentAssociations, error) in + self.utilityNetwork?.associations(withExtent: self.graphicsOverlay.extent) { (containmentAssociations, error) in guard let containmentAssociations = containmentAssociations else { return } - if containmentAssociations.isEmpty { - self.presentAlert(title: nil, message: "This feature contains no associations.") - } containmentAssociations.forEach { association in var symbol = AGSSymbol() if association.associationType == .attachment { @@ -203,7 +204,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } else { symbol = self.connectivitySymbol } - overlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) + self.graphicsOverlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) } // Enable the bar button item to exit the container view. self.exitBarButtonItem.isEnabled = true @@ -259,10 +260,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS super.viewDidLoad() // Load the utility network. loadUtilityNetwork() - // Add self as the touch delegate for the map view. - mapView.touchDelegate = self // Add a graphics overlay. - mapView.graphicsOverlays.add(AGSGraphicsOverlay()) + mapView.graphicsOverlays.add(graphicsOverlay) mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) // Get the legends from the feature service. fetchLegendInfo() @@ -276,8 +275,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS if segue.identifier == "DisplayContentLegendSegue" { let controller = segue.destination as! DisplayContentUtilityNetworkTableViewController controller.presentationController?.delegate = self - // Set the size of the view controller. - controller.preferredContentSize = CGSize(width: 300, height: 200) controller.legendInfos = legendInfos controller.contentSwatches = [ "Bounding box": makeSwatch(symbol: boundingBoxSymbol), From 8ad21ecda6ff64572c14100cdbe67fc8af70b747 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 29 Mar 2021 18:36:35 -0700 Subject: [PATCH 030/109] Addressed review comments --- ...tilityNetworkContainerViewController.swift | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 2cd42d696..cccdabce6 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -19,7 +19,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// The map view managed by the view controller. @IBOutlet var mapView: AGSMapView! { didSet { - mapView.map = makeMap() + makeMap() + mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) } } /// The bar button item to prompt return of the main view. @@ -62,20 +63,22 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// Create a map. /// /// - Returns: An `AGSMap` object. - func makeMap() -> AGSMap { + func makeMap() { let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! - let map = AGSMap(url: webMapURL)! - return map + let map = AGSMap(url: webMapURL) + mapView.map = map } /// Create and load the utility network using the feature service URL. func loadUtilityNetwork() { - utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) + guard let map = mapView.map else { return } + utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: map) utilityNetwork?.load { [weak self] error in - // Add self as the touch delegate for the map view. - self?.mapView.touchDelegate = self if let error = error { self?.presentAlert(error: error) + } else { + // Add self as the touch delegate for the map view. + self?.mapView.touchDelegate = self } } } @@ -121,24 +124,19 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Create a container element using the selected feature. guard let containerElement = utilityNetwork?.createElement(with: containerFeature) else { return } // Get the containment associations from this element to display its content. - utilityNetwork?.associations(with: containerElement, type: .containment) { [weak self] containmentAssociations, error in - guard let self = self else { return } - var contentElements = [AGSUtilityElement]() + utilityNetwork?.associations(with: containerElement, type: .containment) { [weak self] containmentAssociations, _ in // Determine the type of each element and add it to the array of content elements. - containmentAssociations?.forEach { association in - var element: AGSUtilityElement + guard let self = self, let associations = containmentAssociations else { return } + let contentElements: [AGSUtilityElement] = associations.map { association in if association.fromElement.objectID == containerElement.objectID { - element = association.toElement + return association.toElement } else { - element = association.fromElement + return association.fromElement } - contentElements.append(element) } // If there are elements, find their corresponding features. if !contentElements.isEmpty { self.addGraphicsToFeatures(within: containerElement, for: contentElements) - } else if let error = error { - self.presentAlert(error: error) } } } @@ -159,9 +157,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS utilityNetwork?.features(for: contentElements) { [weak self] (contentFeatures, error) in guard let self = self else { return } if let contentFeatures = contentFeatures { - if contentFeatures.count == 1 { - self.presentAlert(title: nil, message: "This feature contains no associations.") - } // Create and add a symbol for each of the features. contentFeatures.forEach { content in let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) @@ -169,9 +164,10 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // The bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. var boundingBox: AGSGeometry? - if self.graphicsOverlay.graphics.count == 1, + if contentFeatures.count == 1, let point = (self.graphicsOverlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in + self.presentAlert(title: nil, message: "This feature contains no associations.") guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } self.identifyAssociationsWithExtent(boundingBox: boundingBox) } @@ -208,8 +204,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // Enable the bar button item to exit the container view. self.exitBarButtonItem.isEnabled = true - // Turn off user interaction to avoid straying away from the container view. - self.mapView.isUserInteractionEnabled = false if let error = error { self.presentAlert(error: error) } @@ -219,6 +213,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // MARK: - AGSGeoViewTouchDelegate func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { + // Turn off user interaction to avoid straying away from the container view. + self.mapView.isUserInteractionEnabled = false // Identify the top most feature that corresponds to the tapped point. mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } @@ -262,7 +258,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS loadUtilityNetwork() // Add a graphics overlay. mapView.graphicsOverlays.add(graphicsOverlay) - mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) // Get the legends from the feature service. fetchLegendInfo() // Add the source code button item to the right of navigation bar. From e2270370afcf2c2ee7677a8b445df3771f39f4a8 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 30 Mar 2021 16:49:57 -0700 Subject: [PATCH 031/109] Removed unnecessary error check --- .../DisplayContentUtilityNetworkContainerViewController.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index cccdabce6..9a9d9ceb2 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -204,9 +204,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // Enable the bar button item to exit the container view. self.exitBarButtonItem.isEnabled = true - if let error = error { - self.presentAlert(error: error) - } } } } From a5283193d819f372e96e48b41321853cf968aef3 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 1 Apr 2021 10:06:42 -0700 Subject: [PATCH 032/109] Merged --- .../CreateLoadReport.storyboard | 116 ++++++ .../CreateLoadReportViewController.swift | 357 ++++++++++++++++++ .../Create load report/README.md | 60 +++ .../Create load report/README.metadata.json | 62 +++ .../Create load report/create-load-report.png | Bin 0 -> 47293 bytes 5 files changed, 595 insertions(+) create mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard create mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift create mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/README.md create mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json create mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard new file mode 100644 index 000000000..71954298f --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift new file mode 100644 index 000000000..f3fcb52e1 --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift @@ -0,0 +1,357 @@ +// Copyright 2021 Esri +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit +import ArcGIS + +class CreateLoadReportViewController: UIViewController { + // MARK: Storyboard views + + /// The table view to display the load reports. + @IBOutlet var tableView: UITableView! + /// The button to reset the phase summaries. + @IBOutlet var resetBarButtonItem: UIBarButtonItem! + /// The button to run the trace and create a load report. + @IBOutlet var runBarButtonItem: UIBarButtonItem! + + // MARK: Properties + + /// A feature service of an electric utility network in Naperville, Illinois. + let utilityNetwork = AGSUtilityNetwork(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")!) + /// The initial conditional expression. + var initialExpression: AGSUtilityTraceConditionalExpression! + /// The trace parameters for creating load reports. + var traceParameters: AGSUtilityTraceParameters! + /// The network attributes for the comparison. + var phasesNetworkAttribute: AGSUtilityNetworkAttribute! + + /// A list of possible phases populated from the network's attributes. + /// By default, they are not included in the load report. + var excludedPhases = [AGSCodedValue]() + /// A list of phases that are included in the load report. + var includedPhases = [AGSCodedValue]() + /// The phase summaries in the load report. + var summaries = [AGSCodedValue: PhaseSummary]() + + /// The number formatter for phase summaries. + let numberFormatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.usesGroupingSeparator = true + return formatter + }() + + /// A struct for the phase summary, which contains the total customers + /// and total load for the phase. + struct PhaseSummary { + let totalCustomers: Int + let totalLoad: Int + } + + // MARK: Methods + + /// Load the utility network. + func loadUtilityNetwork() { + SVProgressHUD.show(withStatus: "Loading utility network…") + utilityNetwork.load { [weak self] error in + SVProgressHUD.dismiss() + guard let self = self else { return } + guard error == nil else { + self.presentAlert(error: error!) + return + } + // Create a default starting location. + guard let startingLocation = self.makeStartingLocation() else { + self.presentAlert(message: "Fail to create starting location.") + return + } + // Get the base condition and trace configuration from a default tier. + guard let utilityTierConfiguration = self.getTraceConfiguration() else { + self.presentAlert(message: "Fail to get trace configuration.") + return + } + // Proceed if the utility network loaded without issue. + self.utilityNetworkDidLoad(startingLocation: startingLocation, traceConfiguration: utilityTierConfiguration) + } + } + + /// Called in response to the utility network load operation completing. + /// - Parameters: + /// - startingLocation: The utility element to start the trace from. + /// - traceConfiguration: The utility tier's trace configuration. + func utilityNetworkDidLoad(startingLocation: AGSUtilityElement, traceConfiguration: AGSUtilityTraceConfiguration) { + // Set the default expression. + initialExpression = traceConfiguration.traversability?.barriers as? AGSUtilityTraceConditionalExpression + + // Create downstream trace parameters with function outputs. + let traceParameters = AGSUtilityTraceParameters(traceType: .downstream, startingLocations: [startingLocation]) + traceParameters.resultTypes.append(.ags_value(with: .functionOutputs)) + + // The service category for counting total customers. + if let serviceCategory = utilityNetwork.definition.categories.first(where: { $0.name == "ServicePoint" }), + // The load attribute for counting total load. + let loadAttribute = utilityNetwork.definition.networkAttributes.first(where: { $0.name == "Service Load" }), + // The phase attribute for getting total phase current load. + let phasesNetworkAttribute = utilityNetwork.definition.networkAttributes.first(where: { $0.name == "Phases Current" }) { + self.phasesNetworkAttribute = phasesNetworkAttribute + // Get possible coded phase values from the attributes. + if let domain = phasesNetworkAttribute.domain as? AGSCodedValueDomain { + excludedPhases = domain.codedValues.sorted { $0.name < $1.name } + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.tableView.reloadSection(.excluded) + self.tableView.isEditing = true + } + } + // Create a comparison to check the existence of service points. + let serviceCategoryComparison = AGSUtilityCategoryComparison(category: serviceCategory, comparisonOperator: .exists) + let addLoadAttributeFunction = AGSUtilityTraceFunction(functionType: .add, networkAttribute: loadAttribute, condition: serviceCategoryComparison) + // Create function input and output condition. + traceConfiguration.functions = [addLoadAttributeFunction] + traceConfiguration.outputCondition = serviceCategoryComparison + // Set to false to ensure that service points with incorrect phasing + // (which therefore act as barriers) are not counted with results. + traceConfiguration.includeBarriers = false + // Assign the trace configuration to trace parameters. + traceParameters.traceConfiguration = traceConfiguration + self.traceParameters = traceParameters + } + } + + /// When the utility network is loaded, create an `AGSUtilityElement` + /// from the asset type to use as the starting location for the trace. + func makeStartingLocation() -> AGSUtilityElement? { + // Constants for creating the default starting location. + let deviceTableName = "Electric Distribution Device" + let assetGroupName = "Circuit Breaker" + let assetTypeName = "Three Phase" + let terminalName = "Load" + let globalID = UUID(uuidString: "1CAF7740-0BF4-4113-8DB2-654E18800028")! + + // Create a default starting location. + if let networkSource = utilityNetwork.definition.networkSource(withName: deviceTableName), + let assetType = networkSource.assetGroup(withName: assetGroupName)?.assetType(withName: assetTypeName), + let startingLocation = utilityNetwork.createElement(with: assetType, globalID: globalID) { + // Set the terminal for the location. (For our case, use the "Load" terminal.) + startingLocation.terminal = assetType.terminalConfiguration?.terminals.first(where: { $0.name == terminalName }) + return startingLocation + } else { + return nil + } + } + + /// Get the utility tier's trace configuration. + func getTraceConfiguration() -> AGSUtilityTraceConfiguration? { + // Get a default trace configuration from a tier in the network. + utilityNetwork + .definition + .domainNetwork(withDomainNetworkName: "ElectricDistribution")? + .tier(withName: "Medium Voltage Radial")? + .traceConfiguration + } + + // MARK: Actions + + @IBAction func resetBarButtonItemTapped(_ sender: UIBarButtonItem) { + summaries.removeAll() + tableView.reloadSection(.included) + resetBarButtonItem.isEnabled = false + } + + @IBAction func runBarButtonItemTapped(_ sender: UIBarButtonItem) { + SVProgressHUD.show(withStatus: "Creating load report…") + + let traceGroup = DispatchGroup() + var summaries = [AGSCodedValue: PhaseSummary]() + for phase in includedPhases { + guard let phaseCode = phase.code else { continue } + // Create a conditional expression. + let phasesAttributeComparison = AGSUtilityNetworkAttributeComparison(networkAttribute: phasesNetworkAttribute, comparisonOperator: .doesNotIncludeAny, value: phaseCode)! + // Chain it with the base condition using an OR operator. + traceParameters.traceConfiguration?.traversability?.barriers = AGSUtilityTraceOrCondition(leftExpression: initialExpression, rightExpression: phasesAttributeComparison) + + traceGroup.enter() + utilityNetwork.trace(with: traceParameters) { results, _ in + defer { traceGroup.leave() } + // If the trace gives not result, return and ignore any error. + guard let results = results else { return } + var totalCustomers = 0 + var totalLoad = 0 + results.forEach { result in + switch result { + case let elementResult as AGSUtilityElementTraceResult: + // Get the unique customers count. + totalCustomers = Set(elementResult.elements.map(\.objectID)).count + case let functionResult as AGSUtilityFunctionTraceResult: + // Get the total load with a function output. + totalLoad = functionResult.functionOutputs.first?.result as? Int ?? 0 + default: + break + } + } + summaries[phase] = PhaseSummary(totalCustomers: totalCustomers, totalLoad: totalLoad) + } + } + // Reload the load report table when trace completes. + traceGroup.notify(queue: .main) { [weak self] in + SVProgressHUD.dismiss() + guard let self = self else { return } + self.summaries = summaries + self.tableView.reloadSection(.included) + self.resetBarButtonItem.isEnabled = true + } + } + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + // Add the source code button item to the right of navigation bar. + (navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["CreateLoadReportViewController"] + // Load the utility network and initialize properties. + loadUtilityNetwork() + } +} + +// MARK: - UITableViewDelegate + +extension CreateLoadReportViewController: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + Section.allCases[section].titleForHeader + } + + func numberOfSections(in tableView: UITableView) -> Int { + Section.allCases.count + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch Section.allCases[section] { + case .included: + return includedPhases.count + case .excluded: + return excludedPhases.count + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: Section.allCases[indexPath.section].cellIdentifier, for: indexPath) + switch Section.allCases[indexPath.section] { + case .included: + let phase = includedPhases[indexPath.row] + cell.textLabel?.text = String(format: "Phase: %@", phase.name) + if let summary = summaries[phase] { + let formattedString = String(format: "C: %@ L: %@", numberFormatter.string(from: summary.totalCustomers as NSNumber)!, numberFormatter.string(from: summary.totalLoad as NSNumber)!) + cell.detailTextLabel?.text = formattedString + } else { + cell.detailTextLabel?.text = "N/A" + } + case .excluded: + cell.textLabel?.text = excludedPhases[indexPath.row].name + } + return cell + } + + func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { + switch Section.allCases[indexPath.section] { + case .included: + return .delete + case .excluded: + return .insert + } + } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + /// Binary search to find the insertion index in a sorted array. + func index(forInserting phase: AGSCodedValue, into array: [AGSCodedValue]) -> Int { + (array as NSArray).index( + of: phase, + inSortedRange: NSRange(array.indices), + options: [.insertionIndex], + usingComparator: { ($0 as! AGSCodedValue).name.compare(($1 as! AGSCodedValue).name) } + ) + } + + switch editingStyle { + case .delete: + let phase = includedPhases[indexPath.row] + includedPhases.remove(at: indexPath.row) + let insertionIndex = index(forInserting: phase, into: excludedPhases) + excludedPhases.insert(phase, at: insertionIndex) + // Remove the summary. + summaries.removeValue(forKey: phase) + // Update the table. + tableView.performBatchUpdates { + tableView.deleteRows(at: [indexPath], with: .automatic) + tableView.insertRows(at: [IndexPath(row: insertionIndex, section: .excluded)], with: .automatic) + } + case .insert: + let phase = excludedPhases[indexPath.row] + excludedPhases.remove(at: indexPath.row) + let insertionIndex = index(forInserting: phase, into: includedPhases) + includedPhases.insert(phase, at: insertionIndex) + tableView.performBatchUpdates { + tableView.deleteRows(at: [indexPath], with: .automatic) + tableView.insertRows(at: [IndexPath(row: insertionIndex, section: .included)], with: .automatic) + } + default: + return + } + // Toggle button state. + runBarButtonItem.isEnabled = !includedPhases.isEmpty + resetBarButtonItem.isEnabled = !summaries.isEmpty + } + + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + true + } +} + +// MARK: Section Enum + +extension CreateLoadReportViewController { + /// A convenience type for the table view sections. + enum Section: Int, CaseIterable { + case included, excluded + + var titleForHeader: String { + switch self { + case .included: + return "Phases, Total Customers(C), Total Load(L)" + case .excluded: + return "More Phases" + } + } + + var cellIdentifier: String { + switch self { + case .included: + return "RightDetail" + case .excluded: + return "Basic" + } + } + } +} + +private extension UITableView { + func reloadSection(_ section: CreateLoadReportViewController.Section) { + reloadSections([section.rawValue], with: .automatic) + } +} + +private extension IndexPath { + init(row: Int, section: CreateLoadReportViewController.Section) { + self.init(row: row, section: section.rawValue) + } +} diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/README.md b/arcgis-ios-sdk-samples/Utility network/Create load report/README.md new file mode 100644 index 000000000..3c2ef4126 --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Create load report/README.md @@ -0,0 +1,60 @@ +# Create load report + +Create a simple electric distribution report that displays the count of customers and total load per phase by tracing downstream from a given point. + +![Image of create load report](create-load-report.png) + +## Use case + +You can use a load report to display the customers per phase as well as the load per phase based on a chosen starting point in a utility network. Load reports are used for electric load restoration and balancing. + +## How to use the sample + +Choose phases to be included in the report. Tap "Run" to initiate a downstream trace on the network and create a load report. Tap "Reset" to clear the phase summaries in the report and start over. + +## How it works + +1. Create and load an `AGSUtilityNetwork` with a feature service URL, then get an asset type, tier, network attributes, and category by their names. +2. Create an `AGSUtilityElement` from the asset type to use as the starting location for the trace. +3. Get a base condition from the utility tier's trace configuration. +4. Create `AGSUtilityTraceParameters` passing in `downstream` trace type and the default starting location. Set its `traceConfiguration` property with the trace configuration above, and set `includeBarriers` to `false`. +5. Create an `AGSUtilityCategoryComparison` where "ServicePoint" category exists. +6. Reset the `functions` property of the trace configuration with a new `AGSUtilityTraceFunction` adding a "Service Load" network attribute where this category comparison applies. This will limit the function results. +7. Set `outputCondition` with this category comparison to limit the element results. +8. Populate the choice list for phases using the network attribute's `codedValues` property. +9. When the "Add" button is tapped, add the selected phase to a phases list. +10. When the "Run" button is tapped, run a trace for every `AGSCodedValue` in the phases list. Do this by creating an `AGSUtilityTraceOrCondition` with the base condition and an `AGSUtilityNetworkAttributeComparison` where the "Phases Current" network attribute does not include the coded value. +11. Display the count of "Total Customers" using the `elements` property of the result, and the result of "Total Load" using the first and only output in `functionOutputs` property. + +## Relevant API + +* AGSUtilityAssetType +* AGSUtilityCategoryComparison +* AGSUtilityDomainNetwork +* AGSUtilityElement +* AGSUtilityElementTraceResult +* AGSUtilityNetwork +* AGSUtilityNetworkAttribute +* AGSUtilityNetworkAttributeComparison +* AGSUtilityNetworkDefinition +* AGSUtilityNetworkSource +* AGSUtilityTerminal +* AGSUtilityTier +* AGSUtilityTraceConfiguration +* AGSUtilityTraceFunction +* AGSUtilityTraceParameters +* AGSUtilityTraceResult +* AGSUtilityTraceType +* AGSUtilityTraversability + +## About the data + +The [Naperville electrical](https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample. + +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + +## Tags + +condition barriers, downstream trace, network analysis, subnetwork trace, trace configuration, traversability, upstream trace, utility network, validate consistency diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json new file mode 100644 index 000000000..5d98d614c --- /dev/null +++ b/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json @@ -0,0 +1,62 @@ +{ + "category": "Utility network", + "description": "Create a simple electric distribution report that displays the count of customers and total load per phase by tracing downstream from a given point.", + "ignore": false, + "images": [ + "create-load-report.png" + ], + "keywords": [ + "condition barriers", + "downstream trace", + "network analysis", + "subnetwork trace", + "trace configuration", + "traversability", + "upstream trace", + "utility network", + "validate consistency", + "AGSUtilityAssetType", + "AGSUtilityCategoryComparison", + "AGSUtilityDomainNetwork", + "AGSUtilityElement", + "AGSUtilityElementTraceResult", + "AGSUtilityNetwork", + "AGSUtilityNetworkAttribute", + "AGSUtilityNetworkAttributeComparison", + "AGSUtilityNetworkDefinition", + "AGSUtilityNetworkSource", + "AGSUtilityTerminal", + "AGSUtilityTier", + "AGSUtilityTraceConfiguration", + "AGSUtilityTraceFunction", + "AGSUtilityTraceParameters", + "AGSUtilityTraceResult", + "AGSUtilityTraceType", + "AGSUtilityTraversability" + ], + "redirect_from": [], + "relevant_apis": [ + "AGSUtilityAssetType", + "AGSUtilityCategoryComparison", + "AGSUtilityDomainNetwork", + "AGSUtilityElement", + "AGSUtilityElementTraceResult", + "AGSUtilityNetwork", + "AGSUtilityNetworkAttribute", + "AGSUtilityNetworkAttributeComparison", + "AGSUtilityNetworkDefinition", + "AGSUtilityNetworkSource", + "AGSUtilityTerminal", + "AGSUtilityTier", + "AGSUtilityTraceConfiguration", + "AGSUtilityTraceFunction", + "AGSUtilityTraceParameters", + "AGSUtilityTraceResult", + "AGSUtilityTraceType", + "AGSUtilityTraversability" + ], + "snippets": [ + "CreateLoadReportViewController.swift" + ], + "title": "Create load report" +} diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png b/arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png new file mode 100644 index 0000000000000000000000000000000000000000..4135192ead01ce94957e3cf3491616cc1742bb80 GIT binary patch literal 47293 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 z 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 hlHuemQW^`7C|c Date: Thu, 1 Apr 2021 12:29:58 -0700 Subject: [PATCH 033/109] Revert "Merged" This reverts commit a5283193d819f372e96e48b41321853cf968aef3. --- .../CreateLoadReport.storyboard | 116 ------ .../CreateLoadReportViewController.swift | 357 ------------------ .../Create load report/README.md | 60 --- .../Create load report/README.metadata.json | 62 --- .../Create load report/create-load-report.png | Bin 47293 -> 0 bytes 5 files changed, 595 deletions(-) delete mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard delete mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift delete mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/README.md delete mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json delete mode 100644 arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard deleted file mode 100644 index 71954298f..000000000 --- a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReport.storyboard +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift deleted file mode 100644 index f3fcb52e1..000000000 --- a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2021 Esri -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import UIKit -import ArcGIS - -class CreateLoadReportViewController: UIViewController { - // MARK: Storyboard views - - /// The table view to display the load reports. - @IBOutlet var tableView: UITableView! - /// The button to reset the phase summaries. - @IBOutlet var resetBarButtonItem: UIBarButtonItem! - /// The button to run the trace and create a load report. - @IBOutlet var runBarButtonItem: UIBarButtonItem! - - // MARK: Properties - - /// A feature service of an electric utility network in Naperville, Illinois. - let utilityNetwork = AGSUtilityNetwork(url: URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")!) - /// The initial conditional expression. - var initialExpression: AGSUtilityTraceConditionalExpression! - /// The trace parameters for creating load reports. - var traceParameters: AGSUtilityTraceParameters! - /// The network attributes for the comparison. - var phasesNetworkAttribute: AGSUtilityNetworkAttribute! - - /// A list of possible phases populated from the network's attributes. - /// By default, they are not included in the load report. - var excludedPhases = [AGSCodedValue]() - /// A list of phases that are included in the load report. - var includedPhases = [AGSCodedValue]() - /// The phase summaries in the load report. - var summaries = [AGSCodedValue: PhaseSummary]() - - /// The number formatter for phase summaries. - let numberFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .decimal - formatter.usesGroupingSeparator = true - return formatter - }() - - /// A struct for the phase summary, which contains the total customers - /// and total load for the phase. - struct PhaseSummary { - let totalCustomers: Int - let totalLoad: Int - } - - // MARK: Methods - - /// Load the utility network. - func loadUtilityNetwork() { - SVProgressHUD.show(withStatus: "Loading utility network…") - utilityNetwork.load { [weak self] error in - SVProgressHUD.dismiss() - guard let self = self else { return } - guard error == nil else { - self.presentAlert(error: error!) - return - } - // Create a default starting location. - guard let startingLocation = self.makeStartingLocation() else { - self.presentAlert(message: "Fail to create starting location.") - return - } - // Get the base condition and trace configuration from a default tier. - guard let utilityTierConfiguration = self.getTraceConfiguration() else { - self.presentAlert(message: "Fail to get trace configuration.") - return - } - // Proceed if the utility network loaded without issue. - self.utilityNetworkDidLoad(startingLocation: startingLocation, traceConfiguration: utilityTierConfiguration) - } - } - - /// Called in response to the utility network load operation completing. - /// - Parameters: - /// - startingLocation: The utility element to start the trace from. - /// - traceConfiguration: The utility tier's trace configuration. - func utilityNetworkDidLoad(startingLocation: AGSUtilityElement, traceConfiguration: AGSUtilityTraceConfiguration) { - // Set the default expression. - initialExpression = traceConfiguration.traversability?.barriers as? AGSUtilityTraceConditionalExpression - - // Create downstream trace parameters with function outputs. - let traceParameters = AGSUtilityTraceParameters(traceType: .downstream, startingLocations: [startingLocation]) - traceParameters.resultTypes.append(.ags_value(with: .functionOutputs)) - - // The service category for counting total customers. - if let serviceCategory = utilityNetwork.definition.categories.first(where: { $0.name == "ServicePoint" }), - // The load attribute for counting total load. - let loadAttribute = utilityNetwork.definition.networkAttributes.first(where: { $0.name == "Service Load" }), - // The phase attribute for getting total phase current load. - let phasesNetworkAttribute = utilityNetwork.definition.networkAttributes.first(where: { $0.name == "Phases Current" }) { - self.phasesNetworkAttribute = phasesNetworkAttribute - // Get possible coded phase values from the attributes. - if let domain = phasesNetworkAttribute.domain as? AGSCodedValueDomain { - excludedPhases = domain.codedValues.sorted { $0.name < $1.name } - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - self.tableView.reloadSection(.excluded) - self.tableView.isEditing = true - } - } - // Create a comparison to check the existence of service points. - let serviceCategoryComparison = AGSUtilityCategoryComparison(category: serviceCategory, comparisonOperator: .exists) - let addLoadAttributeFunction = AGSUtilityTraceFunction(functionType: .add, networkAttribute: loadAttribute, condition: serviceCategoryComparison) - // Create function input and output condition. - traceConfiguration.functions = [addLoadAttributeFunction] - traceConfiguration.outputCondition = serviceCategoryComparison - // Set to false to ensure that service points with incorrect phasing - // (which therefore act as barriers) are not counted with results. - traceConfiguration.includeBarriers = false - // Assign the trace configuration to trace parameters. - traceParameters.traceConfiguration = traceConfiguration - self.traceParameters = traceParameters - } - } - - /// When the utility network is loaded, create an `AGSUtilityElement` - /// from the asset type to use as the starting location for the trace. - func makeStartingLocation() -> AGSUtilityElement? { - // Constants for creating the default starting location. - let deviceTableName = "Electric Distribution Device" - let assetGroupName = "Circuit Breaker" - let assetTypeName = "Three Phase" - let terminalName = "Load" - let globalID = UUID(uuidString: "1CAF7740-0BF4-4113-8DB2-654E18800028")! - - // Create a default starting location. - if let networkSource = utilityNetwork.definition.networkSource(withName: deviceTableName), - let assetType = networkSource.assetGroup(withName: assetGroupName)?.assetType(withName: assetTypeName), - let startingLocation = utilityNetwork.createElement(with: assetType, globalID: globalID) { - // Set the terminal for the location. (For our case, use the "Load" terminal.) - startingLocation.terminal = assetType.terminalConfiguration?.terminals.first(where: { $0.name == terminalName }) - return startingLocation - } else { - return nil - } - } - - /// Get the utility tier's trace configuration. - func getTraceConfiguration() -> AGSUtilityTraceConfiguration? { - // Get a default trace configuration from a tier in the network. - utilityNetwork - .definition - .domainNetwork(withDomainNetworkName: "ElectricDistribution")? - .tier(withName: "Medium Voltage Radial")? - .traceConfiguration - } - - // MARK: Actions - - @IBAction func resetBarButtonItemTapped(_ sender: UIBarButtonItem) { - summaries.removeAll() - tableView.reloadSection(.included) - resetBarButtonItem.isEnabled = false - } - - @IBAction func runBarButtonItemTapped(_ sender: UIBarButtonItem) { - SVProgressHUD.show(withStatus: "Creating load report…") - - let traceGroup = DispatchGroup() - var summaries = [AGSCodedValue: PhaseSummary]() - for phase in includedPhases { - guard let phaseCode = phase.code else { continue } - // Create a conditional expression. - let phasesAttributeComparison = AGSUtilityNetworkAttributeComparison(networkAttribute: phasesNetworkAttribute, comparisonOperator: .doesNotIncludeAny, value: phaseCode)! - // Chain it with the base condition using an OR operator. - traceParameters.traceConfiguration?.traversability?.barriers = AGSUtilityTraceOrCondition(leftExpression: initialExpression, rightExpression: phasesAttributeComparison) - - traceGroup.enter() - utilityNetwork.trace(with: traceParameters) { results, _ in - defer { traceGroup.leave() } - // If the trace gives not result, return and ignore any error. - guard let results = results else { return } - var totalCustomers = 0 - var totalLoad = 0 - results.forEach { result in - switch result { - case let elementResult as AGSUtilityElementTraceResult: - // Get the unique customers count. - totalCustomers = Set(elementResult.elements.map(\.objectID)).count - case let functionResult as AGSUtilityFunctionTraceResult: - // Get the total load with a function output. - totalLoad = functionResult.functionOutputs.first?.result as? Int ?? 0 - default: - break - } - } - summaries[phase] = PhaseSummary(totalCustomers: totalCustomers, totalLoad: totalLoad) - } - } - // Reload the load report table when trace completes. - traceGroup.notify(queue: .main) { [weak self] in - SVProgressHUD.dismiss() - guard let self = self else { return } - self.summaries = summaries - self.tableView.reloadSection(.included) - self.resetBarButtonItem.isEnabled = true - } - } - - // MARK: UIViewController - - override func viewDidLoad() { - super.viewDidLoad() - // Add the source code button item to the right of navigation bar. - (navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["CreateLoadReportViewController"] - // Load the utility network and initialize properties. - loadUtilityNetwork() - } -} - -// MARK: - UITableViewDelegate - -extension CreateLoadReportViewController: UITableViewDelegate, UITableViewDataSource { - func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - Section.allCases[section].titleForHeader - } - - func numberOfSections(in tableView: UITableView) -> Int { - Section.allCases.count - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - switch Section.allCases[section] { - case .included: - return includedPhases.count - case .excluded: - return excludedPhases.count - } - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: Section.allCases[indexPath.section].cellIdentifier, for: indexPath) - switch Section.allCases[indexPath.section] { - case .included: - let phase = includedPhases[indexPath.row] - cell.textLabel?.text = String(format: "Phase: %@", phase.name) - if let summary = summaries[phase] { - let formattedString = String(format: "C: %@ L: %@", numberFormatter.string(from: summary.totalCustomers as NSNumber)!, numberFormatter.string(from: summary.totalLoad as NSNumber)!) - cell.detailTextLabel?.text = formattedString - } else { - cell.detailTextLabel?.text = "N/A" - } - case .excluded: - cell.textLabel?.text = excludedPhases[indexPath.row].name - } - return cell - } - - func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { - switch Section.allCases[indexPath.section] { - case .included: - return .delete - case .excluded: - return .insert - } - } - - func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - /// Binary search to find the insertion index in a sorted array. - func index(forInserting phase: AGSCodedValue, into array: [AGSCodedValue]) -> Int { - (array as NSArray).index( - of: phase, - inSortedRange: NSRange(array.indices), - options: [.insertionIndex], - usingComparator: { ($0 as! AGSCodedValue).name.compare(($1 as! AGSCodedValue).name) } - ) - } - - switch editingStyle { - case .delete: - let phase = includedPhases[indexPath.row] - includedPhases.remove(at: indexPath.row) - let insertionIndex = index(forInserting: phase, into: excludedPhases) - excludedPhases.insert(phase, at: insertionIndex) - // Remove the summary. - summaries.removeValue(forKey: phase) - // Update the table. - tableView.performBatchUpdates { - tableView.deleteRows(at: [indexPath], with: .automatic) - tableView.insertRows(at: [IndexPath(row: insertionIndex, section: .excluded)], with: .automatic) - } - case .insert: - let phase = excludedPhases[indexPath.row] - excludedPhases.remove(at: indexPath.row) - let insertionIndex = index(forInserting: phase, into: includedPhases) - includedPhases.insert(phase, at: insertionIndex) - tableView.performBatchUpdates { - tableView.deleteRows(at: [indexPath], with: .automatic) - tableView.insertRows(at: [IndexPath(row: insertionIndex, section: .included)], with: .automatic) - } - default: - return - } - // Toggle button state. - runBarButtonItem.isEnabled = !includedPhases.isEmpty - resetBarButtonItem.isEnabled = !summaries.isEmpty - } - - func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - true - } -} - -// MARK: Section Enum - -extension CreateLoadReportViewController { - /// A convenience type for the table view sections. - enum Section: Int, CaseIterable { - case included, excluded - - var titleForHeader: String { - switch self { - case .included: - return "Phases, Total Customers(C), Total Load(L)" - case .excluded: - return "More Phases" - } - } - - var cellIdentifier: String { - switch self { - case .included: - return "RightDetail" - case .excluded: - return "Basic" - } - } - } -} - -private extension UITableView { - func reloadSection(_ section: CreateLoadReportViewController.Section) { - reloadSections([section.rawValue], with: .automatic) - } -} - -private extension IndexPath { - init(row: Int, section: CreateLoadReportViewController.Section) { - self.init(row: row, section: section.rawValue) - } -} diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/README.md b/arcgis-ios-sdk-samples/Utility network/Create load report/README.md deleted file mode 100644 index 3c2ef4126..000000000 --- a/arcgis-ios-sdk-samples/Utility network/Create load report/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Create load report - -Create a simple electric distribution report that displays the count of customers and total load per phase by tracing downstream from a given point. - -![Image of create load report](create-load-report.png) - -## Use case - -You can use a load report to display the customers per phase as well as the load per phase based on a chosen starting point in a utility network. Load reports are used for electric load restoration and balancing. - -## How to use the sample - -Choose phases to be included in the report. Tap "Run" to initiate a downstream trace on the network and create a load report. Tap "Reset" to clear the phase summaries in the report and start over. - -## How it works - -1. Create and load an `AGSUtilityNetwork` with a feature service URL, then get an asset type, tier, network attributes, and category by their names. -2. Create an `AGSUtilityElement` from the asset type to use as the starting location for the trace. -3. Get a base condition from the utility tier's trace configuration. -4. Create `AGSUtilityTraceParameters` passing in `downstream` trace type and the default starting location. Set its `traceConfiguration` property with the trace configuration above, and set `includeBarriers` to `false`. -5. Create an `AGSUtilityCategoryComparison` where "ServicePoint" category exists. -6. Reset the `functions` property of the trace configuration with a new `AGSUtilityTraceFunction` adding a "Service Load" network attribute where this category comparison applies. This will limit the function results. -7. Set `outputCondition` with this category comparison to limit the element results. -8. Populate the choice list for phases using the network attribute's `codedValues` property. -9. When the "Add" button is tapped, add the selected phase to a phases list. -10. When the "Run" button is tapped, run a trace for every `AGSCodedValue` in the phases list. Do this by creating an `AGSUtilityTraceOrCondition` with the base condition and an `AGSUtilityNetworkAttributeComparison` where the "Phases Current" network attribute does not include the coded value. -11. Display the count of "Total Customers" using the `elements` property of the result, and the result of "Total Load" using the first and only output in `functionOutputs` property. - -## Relevant API - -* AGSUtilityAssetType -* AGSUtilityCategoryComparison -* AGSUtilityDomainNetwork -* AGSUtilityElement -* AGSUtilityElementTraceResult -* AGSUtilityNetwork -* AGSUtilityNetworkAttribute -* AGSUtilityNetworkAttributeComparison -* AGSUtilityNetworkDefinition -* AGSUtilityNetworkSource -* AGSUtilityTerminal -* AGSUtilityTier -* AGSUtilityTraceConfiguration -* AGSUtilityTraceFunction -* AGSUtilityTraceParameters -* AGSUtilityTraceResult -* AGSUtilityTraceType -* AGSUtilityTraversability - -## About the data - -The [Naperville electrical](https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample. - -## Additional information - -Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). - -## Tags - -condition barriers, downstream trace, network analysis, subnetwork trace, trace configuration, traversability, upstream trace, utility network, validate consistency diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json deleted file mode 100644 index 5d98d614c..000000000 --- a/arcgis-ios-sdk-samples/Utility network/Create load report/README.metadata.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "category": "Utility network", - "description": "Create a simple electric distribution report that displays the count of customers and total load per phase by tracing downstream from a given point.", - "ignore": false, - "images": [ - "create-load-report.png" - ], - "keywords": [ - "condition barriers", - "downstream trace", - "network analysis", - "subnetwork trace", - "trace configuration", - "traversability", - "upstream trace", - "utility network", - "validate consistency", - "AGSUtilityAssetType", - "AGSUtilityCategoryComparison", - "AGSUtilityDomainNetwork", - "AGSUtilityElement", - "AGSUtilityElementTraceResult", - "AGSUtilityNetwork", - "AGSUtilityNetworkAttribute", - "AGSUtilityNetworkAttributeComparison", - "AGSUtilityNetworkDefinition", - "AGSUtilityNetworkSource", - "AGSUtilityTerminal", - "AGSUtilityTier", - "AGSUtilityTraceConfiguration", - "AGSUtilityTraceFunction", - "AGSUtilityTraceParameters", - "AGSUtilityTraceResult", - "AGSUtilityTraceType", - "AGSUtilityTraversability" - ], - "redirect_from": [], - "relevant_apis": [ - "AGSUtilityAssetType", - "AGSUtilityCategoryComparison", - "AGSUtilityDomainNetwork", - "AGSUtilityElement", - "AGSUtilityElementTraceResult", - "AGSUtilityNetwork", - "AGSUtilityNetworkAttribute", - "AGSUtilityNetworkAttributeComparison", - "AGSUtilityNetworkDefinition", - "AGSUtilityNetworkSource", - "AGSUtilityTerminal", - "AGSUtilityTier", - "AGSUtilityTraceConfiguration", - "AGSUtilityTraceFunction", - "AGSUtilityTraceParameters", - "AGSUtilityTraceResult", - "AGSUtilityTraceType", - "AGSUtilityTraversability" - ], - "snippets": [ - "CreateLoadReportViewController.swift" - ], - "title": "Create load report" -} diff --git a/arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png b/arcgis-ios-sdk-samples/Utility network/Create load report/create-load-report.png deleted file mode 100644 index 4135192ead01ce94957e3cf3491616cc1742bb80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47293 zcmaHS1#}!SvaKmGL+qGiW@e0;dCZKl$IQ$OF*7qWQ(}gg#>~vj%=DezeQ)=_^ZxHS zeWa4AN>Zz(uBo~Tm6sDogu{UY0|P^pln_w_0|WmG1_q%5^ZBEMAOnu>BY`pzlobR6 ztBr<#G5GXB6BQas_}3iB|H?zC{1pp6dp`Y0U~MHd9KgWf(f;1xU}+gx zAERY4Q&x9WmzCi*w6UT$FtYgpq<6Kl{VN5=)oiGNVM#HNmpw%iO1 zE-o(gE-dsm_9hHWTwGiXjLZzo%yb_dbPjITjs~uD)(#~9RPtYXM1T&4_GY$@W;WJ@ zfAt#tuyJzaB_{sc(0^b5?5Crd@xNQLcKFw@J_g9}w}ydi@Uqb)0=6{vc__rhz2N&~yivCB{zeIT${yx_Kc+CHt!+(^1 zOd=l~55s@I5PWcm)qkkKzy!b~MFf>y!A~-weO3Bq2gX&^)!onA!+gIAeiHnu6`_zH zTATi(<#Ea|Pfv!4oM{MCiOrmq2?s5o9LKPNGR)tXRZz6WQC&Srr|JB4?7WTlc(=Co zL@Nnu5!>~A_51F~h|gFCm&4gAm)Sb*wG1f{6chvmxF5LyVLPlT6e_r%uYf=o3Je4p zqmTe0;e-(kl;4z*{AZ!R6)2Q`(Enf-CWJ{K4`4=tgMotb7l7qKL4ko`#fA{fVZ~1H zlmC!Ifs)$zt0`ybLsj8W4niOV#JeC=)Wp033o<;EqpGNi*f47-wP=}CxkvW5WM}=; zLoTzpEHc!@aAk}E`RO+7G;-`T)m+wXGw3*2CUC!ec<@X(Gj4{ddMBhmv%b`s@W9wn zOvx;Odv;N_#Ptkz$`8risRVBkPs^uS4L+*e!%uK{<8uJxw69}y$q`LvalDMeQ_3g> zz;@jEAM(LYUt>`4S^3&k(oUwCgA|D>NtNs=OeAMJ20>waG_Hl(QiY24%4H4Yl_KzL zdDD_ufy=&Kv5~%4u43t|r3+eQLGUz=&TTYA%qlGnIGIGLR#S!c)y9sSIi2LD)FeYE zD9HlQ=jMH9)R_(~H6(3{8G5ob@(0my@lz^^ifMXe`5h}7QgGBp!{I@SziHy)P7~Se z(z9t2BIe8#pPUPgZbunUA;DR1e7FZEl(>hM+**N;$XBE;ib)gQb%`p>Pfuf0R<2c+ zDV^e~Yb{##VkU4?tg~_i-=<=U8iD`$FI`Efp1YvXu=c zNQ-}&>@f&9(@Xwn(MKeK#6g*G4@w(bp!nFf+@R*_pT-YlJM7tb-d?NLoz{ z%#E8%@cH%=L$MS`^!QD~er=QlII%!qchq=#wR{O*aPDTclktv69}sm+Y{RfZ-waTv z)By~|&aKuL=nI#EvtOURF>luy)LBT!I-aa)?!7rw^0;?P4dJDd5xn)*PPw>>4=rm` z>O3{X7BX1IiI2G}*^`$QDOGOH1S$PQhG|p#A`rl!D^Er7R+cRDctL2k{CgK%hiXBC znBf)J*!J>UHjYJiKOhYo#%rKCnRZs&{oDG}Mh~gNAB=sv>#%~h8Yy<#5kP{68qt-u z(;Itca2^C>yJ*@@rz*J`52tF`%vh}wh0pK`?IID-{#2HvP_b}tOg1QPI_Z}p*KM!Y zZUq3J#6_D$4YXDkr$moe|J`0^G?*~Pe0I}ee`gXMYaOsWxIX47tQkF?Ft=J);3^*U%|})b+uJib zf&0BbhmQHV2ysdZ^ZA90Y$|V{Rp>}RP;prsFHjSxKx!2|nzZPnP1F4CJ}e8sxcH|4XLMy|_F$ZcFT(@D*kV+>ZnTe3o_Q zi4s@s0ONhu>S}wFVQ>q&8N|fWI+VJOLrnrWF1pv+Nix)pX=csz+-ZL78j%YpEzT_C z#G$4sv!oYOG4HB8&A(3I2~<6;E6i(97)Z zTTK_Hnb6UB%TnBAg&WhmeLIWY9G|3@i9 zCFC-N)q&D4CV(pu1?-qNX~k4EwzS!@5Ru^^5lw)~wz+fD$C9PBNIpwg_cV&~lxZrWitF7U^j7BJb1}_53?Yl>ZcGt2 zbhUn-;D`2Ib19F(Ivyx}1$^Xh(hBj2G9w{-!s4ntyrC^;@%#jp1_chhDGQU(Y#5HQ z7Ir9{_Elx?e%$4w;m}!f98SXTU0$$JwIe%cXthgS+6WFr~ zj9VlYcCMn28)Z02thh5*En&aW{1_$DxH6OkdhH^e3XOuiGJTrB1?QTKMLByybJj@w zOC&s*k8JIUrm{J}NsikmW~HMb^9FZOGU+fr!wUX>XsgpE*0A_4p?W8qHhq08`7NJ& zDC*V&c&W2oc>43`Ug7A_NCFP#g#$(3y7%d@%q-t7A1|lSHZ!$S({~AB^0N%CIL%;1 zgGE@aXz3JP@Z^T{Cz15{Su93ebddt#XjS&&r2`&wHo8mmPpOM=mk_40I9A_fP3gjC zF@E2kLJUi5p+ZIedDF`(>eSlDl$1-BSKkurW~rP8fpD2oKeIC_;kuR}CSy*Gp);H+z~)2`E1 zdpgHA@bC#s=~gB<7dOR(5}Z?=a_iuMU4ZJB*n^iulRh`FmFXY0aOy83J-FEn4 z^mx`Gm0m^VGCOmZ)z+Mqhz6b|X0tN?Kf1N^%rJ@mZa~F~Wvqy%)2Q*J64Fb~7EeIp ziH3%88nO*^6K-Z@rph;`Xbs#8HY-?6aKCqU2+*>n*M<^Qs7~*>xf)ZwFEt)*Pf?;i zPRW>>TD==@{?08NIyto`Bg4TvBm}dV8POl+r6S|S650u9ss&G1>?-ypXyrTWKL(TX z5pC?GBpj239&o*e6f?E1+V=cZ`8MN4rGhYwt_Y_MU>U4v_);OP%kyT+Fdy459=IiL z|EQ-*J=30Vngw^x{qrtKRg|xM=_BrM?kg;-y_7M`^42QPTGwO0yfMnBtl|@}G&e{QtNYW8YwI`c0OS$Lt-l#cmQ4+8Pn-_w=S0S!(wV zU0TSlGi2{q@6NwPo$9|JpMJ(sYKOB>3j?;%c7_0Q1lpUB<}t)|k#7s}_|MU%oQ|7}EwNLRyG=hW} z{o+R`pSE2R!Uqk7g!W-|ek0e1T=W%i5cx1m_c)Jo$HD!213#?Q5ZDC)cEX8oUp{P5 zt|<2dhyS1YZ)=^qTr!bJ9}R%}i4o`cybcfnoP)#Se%`1D6}^o zLxpB3BrHb7Z-_`GsV#(9Y@J}KJS%MrAFFJ$ey#kqr;Qec!zuKBbvcm(TL=ju4hu1& z<^*i9(GB{lqAU?YL|1V9=pI-QyjqhL878=4$4P zV;?A8n1<9wvY6nGrp^`hfe{ZQw3hOWZs;J3vF=#s#;1LAbC3dFsGRORgnLNKSv!yB zULI!88LH1l9=1WVgN{7zB#P0rzQt*!C47P#8+U0}rdINv)6y(Q%T4aMj54~Fg?Bh>N`}7Q(pgs2rFK}jPfA@yJ-7Z|*X6jcT#C;;gL1Hj=Eg}B`&iavw0HhA^b^f}Fx{aU zln$s&mPN+Uz;xG{(G1RB(^$LT{c_bGs(WRoY8$U z56;Y~f?I4KOLA-7!jIh|n+p-f()CAD*TcTg%=wk?}cOeCPSL zBzd}Uj<1Oyciq4JJ8Jr}VWGO!db48A81ri@LSy94;g-+R>8sHL?CS2CG=}6_9qM%e z+a~lXLLAxp3ehpXHqCYPDsl2EziQsHXx8J7`yp$gW=R2zPDJ>TZ-(IPP)uo@^}vZD z*YTO3{gO&=fhnN$Wj8&XEI+*J*U@{g4$v0EvIsxSV`=r3RE;;J@i zUpS@6o8Iloxt~|5;y&0wU@~wN#;-OuyHoBe8RW>zAzt)q?aT94nW)$z+YaZfm|Nh) zDz#jiA0EPs174Qhqef%2a^EsE5#NIKnI>zUT)MMaNi%xdu=)1l2Nb!98?h_3V~_xg zG=NiCW+QMz!P4B;ze;SeHkCW>mwn`&Y3dm4D0D>EZ+4tL4j1cGnP)3KY_7)E6_?!~ zr3-36L-E%@9Ktr@ys0auRLM zeu<2Ds^C33ZdK&nvNPo>`^A9zO&N(HT|;~1+)&tZguh#?JcVn3V>-*#AN;H0VNA)PFt|heAJR^=N%WXHE*ZJCXNUWR zPG&`mYG(aO&bO+#uCU74~2+A0A}i=BWF#OZgL)<%6~|q#DGo8fA*MXR&G@cl#X@Br=*nO z^kBw`pSdUszH#hJy2^ZNi1Q}lPO}yFO{|*dZjRH_Q8FFd^P+0m&q zmq)eYZaf)Z7dX}#Hm@R)26v}@`&jQZ$2a`_vbTNrjh{AIHC0NaT@K5kD-aRp7XE7{ zLI!vElH;3RNZR*_7pv!;vvSPAF^aIl(-~T;oU(p29x#xJ7Oqc3w47CF>)g?tz*o!*~OpQaM^9LF{_PFH46B85D8{d`&u^ z_6u3OeAeG5dIN(64$y_7nl6v?YHLYRCXET#Rao?gWpxam zM)4Jov-m@)C7kUVWW{Tf0C!|7hSnyGA$YxILXxTzLbUO73#1&rn;VJL_Z*x>?`HAO zUTvAoDmG~P6Y8(!o@SNtD6&7xt8>Z~C2?k*XCz+Hr-Tge2JP-;G>xIi$3L4| zf0z_HX3QuSz1iq#@OmUiwAK_?c(Vca-p(<&9x2*^2L<$To$cznElvR^SvtgqHYe0p zEe$b|;qW8AzdRgjM;^Psqf$kqmj};ZhiP-&lbkmpzsu1|uzZciqX{n9Yk$anmB_>v#~9KxQ6THYB@DOE=vymLxP7wF%c5l zMn&!K3y&yo9u>_37!{y}it74{>#8IWuyiNgGb=1&;UbapH6`pvFw6PPK=#>VUsn$cs39BzOvtMu<%r*k(*^g$<6g8EJ-aBj?9eFznE6d)Wc9!e5 zpM-|AIskI7{e;-nUdxRNc(jQL!!Zuu2f6gH3u&JCGQTF;_tBy4R-a-FwWT+KOmtHT zg~=V`RivAScJ7fAI!GLu->urYl1!#6n?}x+Y*28&5?hx?3mq`rc%kZboCPqSA7M zJ*&IAY~55DgE#CARWB2N!K}H7)b|>gw8um1V^?Z)tJM2lu5E^CE$R7gNToA_5LlRa zwVJLQgHNZGiji6fFaCx)OP8p&1TZIR)uoCZp{E{NTw-VZWo;+md{@A^igVvFiphQ#Kq2L3S4jJOCbvw? z`*K=%H4Iw~Vle3-?-KyoJLs4kuF$A?v)N{?*mWyDK1U~~Rzh{w6!z^l%@a7; zBmaJv4mTRj^eE^9yZuvi`)$&1Ple&rMIW_R+|9PH=o2efWI^8gCxb(8DW|Q6lO*MUMO}wmkztU=lZ%`k8bAH4Ovq96I72E0MW!4kbn+lgUE0`=|`2oj;95R(7R7&zNJ=G z$jj0uJh{#(lZh^2(BdROxJj*hfmDGecI zMzCtt(cjbLl=X0iL~UJ%GTGYXfaM2Wr}-w*;c{o9<%37A<+41X#*t~OqL~1JY7oH; zBXPOj8d+syR#x%;(!#CE^603RT;jD2rz%LwQL8*$K71}!QCptgrp)&nS8in6<2jyK z!M)^>y!K<)@_hIm9Vq^r%Itzp-L{~Ep=ca~%ygW^2q^{>Owm~7wHB#cJ zDVs(&ptD@EXJfsA?CTij(^C;*t{eHrabE{lJq7+g0o;U_~iLnY7X zYV0%?(f z(rK042e6KdTD9NJ_zs=w{@m3lt-P(!(z0YAZ2$yW6$eWI|3o5}%NA+{e|s;rCI>3a zzdx;t+DB-XkH1O!xb24$4^6?QnwxBozC>$7Ml&;s^~}OwlQt{CW4q~4XnZf1pX1e| z6y{q~=(t$<>ajVf7M_&PqFkc7;Ozs@t$nE(54S&tb=b)oXNVcF)*x!9A8e!>XaTy} z3$JU`?L0=Zn}Il#rClm*=2;5kpyRkddpKhZN9QovMXkIpK3?rqug68?E_sZOy)dh# zxGPlY*XfupGYwekS~Q~TK<}ifvTa`J+E2L!>=1A;BoiRJ4ngrRPxxb^e%`L~asckO zv~%~d6zZ6;y_D(%^9d6;e}c?VvpPH7tsqU_F^3LgOUXxnciXp9fN(z!Sm39G+@qxu) zBQuiP*s`%Ie!22N;Wp^hdVG%AgOd4&u?fqF$==cPk0oiDV_G50=+Tj?*i@?-n5u9n zH@6re4buV~^Th_`cmc|T?G{yvqp;d0A#WFu=i@>AHqf81a>$cg=Z(kVcLR2^E2`3U z2l#Eilm(>L;j*hz=hQfqs9dW|s^b`##@m%K)g*cxdd2j`H*9ZJlS8hY_6n^m3V_~k zIl13PC7xTUOmznYT018UNXd~ld&3_OU5!Mmh4$r+eOW2{`cWaSvsOg)ornK&W*cVx z?qab1^nliFcRAf?BtqBz5V?Q&!c0fz8i%94dI=wHchutwc!lnzQd8Es@AU&fv&Y{e zIQE)txC_D*8?K@gWq!=?tJ@g5Wj@9|PQ)fYZ*gL5k8qX^^fXC zkB&|Z>8#b(bu+EZcu!=q51L${h+pFnz~Fz5s%SZt&5SS~nDi53B%GM^+kdl(Z-_J60t%`@Q~MBEg~j+N)?{vCLUyxy3;UMEV6{jO7e0w#o^K8Dns#j z6JWUWNKhqhI&(o8$(;uI>o_gD{MtGT$7sC$4eOB0D}1N?w7z!)V@gmQ95JQK$yl!C z#JffLx*@51yA{OW(W$NXDBsJA{Mi#9Rs^y zIW~8|CH|~vcYI>C;ia473r{KSTH;{MVP*4ZK_x!iPmXT)I=OlVCStj^3ctt zZKVS&MGeKA39F#LIb<2#S8eZ>ws7C9|1>cva#b$F+q^AqI)wL5HAXvFXm4y|vMGN# zoGCQcJ91Z)E-k4@K=)ZDq6;w|Y*{~#-I60?7Kuz;otgOUIfjvXn|b?0FZg?B|0^g5 zHZzf`Zub_m`C$7_LUnYV3>Tj+=H%^1%K1u@nr??dxUv&fayMEFRwO#Zae9oN77d+y zF2#X=EmIs)yyJOUco$Bict!3Q64{iGjQHV1dm^p3aX!!MVPoBHA@LACDYK;_2by)d z>i)5kKdOeqIlad79=+Lj!r?5=b|#bbMOwI9yu!r$Jq_MO^ItZL0K{uZO^_DDS%Uxk ztq!TvRr|}^>6EcZ@Fl8{)g5H{Zeq4|tR%rXFnn@Fd~SHqY!$ft1mU)`TzyP(E46qt zFGO`xGoH0J(IE=3Nuc1XmC{5vmS|?t8k%GKRQL9!vAT4VsghQ<$%-bX$xC^n)cBWB z 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 hlHuemQW^`7C|c Date: Fri, 2 Apr 2021 08:37:00 -0700 Subject: [PATCH 034/109] Support SS7 --- ...ntentUtilityNetworkContainerViewController.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 9a9d9ceb2..c58c6cb9e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -19,6 +19,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// The map view managed by the view controller. @IBOutlet var mapView: AGSMapView! { didSet { + AGSAuthenticationManager.shared().delegate = self makeMap() mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) } @@ -28,7 +29,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS @IBOutlet var legendBarButtonItem: UIBarButtonItem! /// A feature service for an electric utility network in Naperville, Illinois. - let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/arcgis/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! + let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! var utilityNetwork: AGSUtilityNetwork? let graphicsOverlay = AGSGraphicsOverlay() /// The default or previous viewpoint before entering the container view. @@ -64,7 +65,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// /// - Returns: An `AGSMap` object. func makeMap() { - let webMapURL = URL(string: "https://ss7portal.arcgisonline.com/arcgis/home/item.html?id=5b64cf7a89ca4f98b5ed3da545d334ef")! + let webMapURL = URL(string: "https://sampleserver7.arcgisonline.com/portal/home/item.html?id=813eda749a9444e4a9d833a4db19e1c8")! let map = AGSMap(url: webMapURL) mapView.map = map } @@ -282,3 +283,11 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS return .none } } + +extension DisplayContentUtilityNetworkContainerViewController: AGSAuthenticationManagerDelegate { + func authenticationManager(_ authenticationManager: AGSAuthenticationManager, didReceive challenge: AGSAuthenticationChallenge) { + // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. + let credentials = AGSCredential(user: "editor01", password: "S7#i2LWmYH75") + challenge.continue(with: credentials) + } +} From 26452ad5f484b5f28ab1f4ea7c0a5c29eda00825 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 2 Apr 2021 14:33:55 -0700 Subject: [PATCH 035/109] Adjusted URLs for SS7 --- .../DisplayContentUtilityNetworkContainerViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index c58c6cb9e..4b96cce65 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -87,8 +87,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// Get the legend information provided by the feature layers used in the utility network. func fetchLegendInfo() { // Create feature tables from URLs. - let electricDistributionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("105")) - let structureJunctionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("900")) + let electricDistributionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("1")) + let structureJunctionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("5")) // Create feature layers using the feature tables. featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in From 7e1041e67a01a29368d52c95ca4ec4b32225eaee Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 7 Apr 2021 17:30:37 -0700 Subject: [PATCH 036/109] Added legend item struct --- ...yContentUtilityNetworkContainer.storyboard | 4 +- ...tilityNetworkContainerViewController.swift | 130 ++++++++++++++---- ...entUtilityNetworkTableViewController.swift | 31 +++-- 3 files changed, 121 insertions(+), 44 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard index 6fa83bb67..adb81a522 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard @@ -63,10 +63,10 @@ - + - + diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 4b96cce65..b9da19ec3 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -37,12 +37,20 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// An array containing information about the feature services' legends. var legendInfos = [AGSLegendInfo]() var featureLayers = [AGSFeatureLayer]() + private var legendItems = [LegendItem]() // The symbols used to display the container view contents. let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .green, width: 3) let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) + /// The data source for the legend table. + private var symbolsDataSource: SymbolsDataSource? { + didSet { + legendBarButtonItem.isEnabled = true + } + } + /// The action that is prompted when exiting the container view. @IBAction func exitContainerView() { // Disable the bar button item since container view will be exited. @@ -95,8 +103,12 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Get the legend information of each layer. layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } - self.legendBarButtonItem.isEnabled = true +// self.legendBarButtonItem.isEnabled = true self.legendInfos.append(contentsOf: legendInfos) + self.makeSwatches(legend: legendInfos) { legendItems in + self.legendItems.append(contentsOf: legendItems) + self.symbolsDataSource = SymbolsDataSource(legendItems: self.legendItems) + } if let error = error { self.presentAlert(error: error) } @@ -104,6 +116,27 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } + private func makeSwatches(legend: [AGSLegendInfo], completion: @escaping ([LegendItem]) -> Void) { + let swatchGroup = DispatchGroup() + var legendItems = [LegendItem]() + legend.forEach { legendInfo in + if let symbol = legendInfo.symbol { + swatchGroup.enter() + symbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + if !legendInfo.name.isEmpty, let image = image { + defer { swatchGroup.leave() } + legendItems.append(LegendItem(name: legendInfo.name, image: image)) + } else { + swatchGroup.leave() + } + } + } + } + swatchGroup.notify(queue: .main) { + completion(legendItems) + } + } + /// Get the container feature that was tapped on. /// /// - Parameters: @@ -230,23 +263,23 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// /// - Parameter symbol: The symbol to make a swatch from. /// - Returns The resulting image that represents the swatch. - func makeSwatch(symbol: AGSSymbol) -> UIImage { - let swatchGroup = DispatchGroup() - var swatchImage = UIImage() - swatchGroup.enter() - DispatchQueue.global(qos: .userInitiated).async { - symbol.createSwatch(withBackgroundColor: nil, screen: .main) { [weak self] (image, error) in - if let image = image { - swatchImage = image - } else if let error = error { - self?.presentAlert(error: error) - } - swatchGroup.leave() - } - } - swatchGroup.wait() - return swatchImage - } +// func makeSwatch(symbol: AGSSymbol) -> UIImage { +// let swatchGroup = DispatchGroup() +// var swatchImage = UIImage() +// swatchGroup.enter() +// DispatchQueue.global(qos: .userInitiated).async { +// symbol.createSwatch(withBackgroundColor: nil, screen: .main) { [weak self] (image, error) in +// if let image = image { +// swatchImage = image +// } else if let error = error { +// self?.presentAlert(error: error) +// } +// swatchGroup.leave() +// } +// } +// swatchGroup.wait() +// return swatchImage +// } // MARK: - UIViewController @@ -265,16 +298,21 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // MARK: - Navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if segue.identifier == "DisplayContentLegendSegue" { - let controller = segue.destination as! DisplayContentUtilityNetworkTableViewController - controller.presentationController?.delegate = self - controller.legendInfos = legendInfos - controller.contentSwatches = [ - "Bounding box": makeSwatch(symbol: boundingBoxSymbol), - "Attachment": makeSwatch(symbol: attachmentSymbol), - "Connectivity": makeSwatch(symbol: connectivitySymbol) - ] - } + if segue.identifier == "DisplayContentLegendSegue", + let controller = segue.destination as? UITableViewController { + controller.presentationController?.delegate = self + controller.tableView.dataSource = symbolsDataSource + } +// as! DisplayContentUtilityNetworkTableViewController +// controller.presentationController?.delegate = self +// controller.legendInfos = legendInfos +// controller.contentSwatches = [ +// "Bounding box": makeSwatch(symbol: boundingBoxSymbol), +// "Attachment": makeSwatch(symbol: attachmentSymbol), +// "Connectivity": makeSwatch(symbol: connectivitySymbol) +// ] +// controller.images = images +// } } // MARK: - UIAdaptivePresentationControllerDelegate @@ -291,3 +329,39 @@ extension DisplayContentUtilityNetworkContainerViewController: AGSAuthentication challenge.continue(with: credentials) } } + +// MARK: - SymbolsDataSource, UITableViewDataSource +private class SymbolsDataSource: NSObject, UITableViewDataSource { + /// The legend items for the legend table. + private let legendItems: [LegendItem] + + init(legendItems: [LegendItem]) { + self.legendItems = legendItems + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + legendItems.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayContentLegendCell", for: indexPath) + let legendItem = legendItems[indexPath.row] + cell.textLabel?.text = legendItem.name + cell.imageView?.image = legendItem.image + return cell + } + + func numberOfSections(in tableView: UITableView) -> Int { + 1 + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + "Symbol Styles" + } +} + +// MARK: - LegendItem +private struct LegendItem { + let name: String + let image: UIImage +} diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift index 0a8d6cfc0..388b45c00 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift @@ -18,6 +18,7 @@ import ArcGIS class DisplayContentUtilityNetworkTableViewController: UITableViewController { var legendInfos = [AGSLegendInfo]() var contentSwatches = KeyValuePairs() + var images = [(String, UIImage)]() // Set the number of rows. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -32,20 +33,22 @@ class DisplayContentUtilityNetworkTableViewController: UITableViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayContentLegendCell", for: indexPath) // Add the container view swatches to the legend after the feature layer legend information. - if indexPath.row >= legendInfos.count { - let contentSwatch = indexPath.row - legendInfos.count - cell.textLabel?.text = contentSwatches[contentSwatch].key - cell.imageView?.image = contentSwatches[contentSwatch].value - cell.setNeedsLayout() - } else { - // Add the information provided by the feature layers to the legend. - let legendInfo = legendInfos[indexPath.row] - cell.textLabel?.text = legendInfo.name - legendInfo.symbol?.createSwatch { (image, _) in - cell.imageView?.image = image - cell.setNeedsLayout() - } - } +// if indexPath.row >= legendInfos.count { +// let contentSwatch = indexPath.row - legendInfos.count +// cell.textLabel?.text = contentSwatches[contentSwatch].key +// cell.imageView?.image = contentSwatches[contentSwatch].value +// cell.setNeedsLayout() +// } else { +// // Add the information provided by the feature layers to the legend. +// let legendInfo = legendInfos[indexPath.row] +// cell.textLabel?.text = legendInfo.name +// legendInfo.symbol?.createSwatch { (image, _) in +// cell.imageView?.image = image +// cell.setNeedsLayout() +// } +// } + cell.textLabel?.text = images[indexPath.row].0 + cell.imageView?.image = images[indexPath.row].1 return cell } From 032dec620546e2036c1d634b0942e990e7385a15 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 8 Apr 2021 17:05:22 -0700 Subject: [PATCH 037/109] Made containerViewSymbol struct --- ...tilityNetworkContainerViewController.swift | 79 +++++++++++++------ 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index b9da19ec3..76c8a32aa 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -37,12 +37,20 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// An array containing information about the feature services' legends. var legendInfos = [AGSLegendInfo]() var featureLayers = [AGSFeatureLayer]() - private var legendItems = [LegendItem]() // The symbols used to display the container view contents. - let boundingBoxSymbol = AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) - let attachmentSymbol = AGSSimpleLineSymbol(style: .dot, color: .green, width: 3) - let connectivitySymbol = AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) + let boundingBoxSymbol = ContainerViewSymbol( + name: "Bounding box", + symbol: AGSSimpleLineSymbol(style: .dash, color: .yellow, width: 3) + ) + let attachmentSymbol = ContainerViewSymbol( + name: "Attachment", + symbol: AGSSimpleLineSymbol(style: .dot, color: .green, width: 3) + ) + let connectivitySymbol = ContainerViewSymbol( + name: "Connectivity", + symbol: AGSSimpleLineSymbol(style: .dot, color: .red, width: 3) + ) /// The data source for the legend table. private var symbolsDataSource: SymbolsDataSource? { @@ -97,38 +105,55 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Create feature tables from URLs. let electricDistributionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("1")) let structureJunctionTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("5")) + let legendGroup = DispatchGroup() // Create feature layers using the feature tables. featureLayers = [electricDistributionTable, structureJunctionTable].map(AGSFeatureLayer.init) featureLayers.forEach { layer in + legendGroup.enter() // Get the legend information of each layer. layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } + defer { legendGroup.leave() } // self.legendBarButtonItem.isEnabled = true self.legendInfos.append(contentsOf: legendInfos) - self.makeSwatches(legend: legendInfos) { legendItems in - self.legendItems.append(contentsOf: legendItems) - self.symbolsDataSource = SymbolsDataSource(legendItems: self.legendItems) - } +// self.makeSwatches(legend: legendInfos) { legendItems in +// self.legendItems.append(contentsOf: legendItems) +// self.symbolsDataSource = SymbolsDataSource(legendItems: self.legendItems) +// } if let error = error { self.presentAlert(error: error) } } } + legendGroup.notify(queue: .main) { [weak self] in + guard let self = self else { return } + let symbols = self.legendInfos + [self.boundingBoxSymbol, self.attachmentSymbol, self.connectivitySymbol] + self.makeSwatches(legend: symbols) { legendItems in + self.symbolsDataSource = SymbolsDataSource(legendItems: legendItems) + } + } } - private func makeSwatches(legend: [AGSLegendInfo], completion: @escaping ([LegendItem]) -> Void) { + private func makeSwatches(legend: [Any], completion: @escaping ([LegendItem]) -> Void) { let swatchGroup = DispatchGroup() var legendItems = [LegendItem]() - legend.forEach { legendInfo in - if let symbol = legendInfo.symbol { - swatchGroup.enter() - symbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in - if !legendInfo.name.isEmpty, let image = image { - defer { swatchGroup.leave() } - legendItems.append(LegendItem(name: legendInfo.name, image: image)) - } else { - swatchGroup.leave() - } + var symbol = AGSSymbol() + var name = String() + legend.forEach { symbolItem in + if let legendInfoItem = symbolItem as? AGSLegendInfo, !legendInfoItem.name.isEmpty { + name = legendInfoItem.name + symbol = legendInfoItem.symbol! + } else if let containerViewSymbol = symbolItem as? ContainerViewSymbol { + name = containerViewSymbol.name + symbol = containerViewSymbol.symbol + } + swatchGroup.enter() + symbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + if let image = image { + defer { swatchGroup.leave() } + legendItems.append(LegendItem(name: name, image: image)) + } else { + swatchGroup.leave() } } } @@ -136,6 +161,8 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS completion(legendItems) } } + + func makeSwatch(name: String, symbol: AGSSymbol) -> /// Get the container feature that was tapped on. /// @@ -220,7 +247,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// - Parameter boundingBox: The gemeotry which represents the boundaries of the extent. func identifyAssociationsWithExtent(boundingBox: AGSGeometry) { // Add the bounding box symbol. - graphicsOverlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol)) + graphicsOverlay.graphics.add(AGSGraphic(geometry: boundingBox, symbol: boundingBoxSymbol.symbol)) let geometry = AGSGeometryEngine.bufferGeometry(graphicsOverlay.extent, byDistance: 0.05)! mapView.setViewpointGeometry(geometry) { [weak self] _ in guard let self = self else { return } @@ -230,9 +257,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS containmentAssociations.forEach { association in var symbol = AGSSymbol() if association.associationType == .attachment { - symbol = self.attachmentSymbol + symbol = self.attachmentSymbol.symbol } else { - symbol = self.connectivitySymbol + symbol = self.connectivitySymbol.symbol } self.graphicsOverlay.graphics.add(AGSGraphic(geometry: association.geometry, symbol: symbol)) } @@ -356,7 +383,7 @@ private class SymbolsDataSource: NSObject, UITableViewDataSource { } func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - "Symbol Styles" + "Legend" } } @@ -365,3 +392,9 @@ private struct LegendItem { let name: String let image: UIImage } + +// MARK: - ContainerViewSymbol +struct ContainerViewSymbol { + let name: String + let symbol: AGSSymbol +} From 80720262c48e3e72a3575cdd00db2a7663bc5246 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 9 Apr 2021 16:53:07 -0700 Subject: [PATCH 038/109] Cleaned up makeSwatches function --- ...tilityNetworkContainerViewController.swift | 79 ++++++------------- 1 file changed, 22 insertions(+), 57 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 76c8a32aa..a1f8565ff 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -114,12 +114,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS layer.fetchLegendInfos { [weak self] (legendInfos, error) in guard let self = self, let legendInfos = legendInfos else { return } defer { legendGroup.leave() } -// self.legendBarButtonItem.isEnabled = true self.legendInfos.append(contentsOf: legendInfos) -// self.makeSwatches(legend: legendInfos) { legendItems in -// self.legendItems.append(contentsOf: legendItems) -// self.symbolsDataSource = SymbolsDataSource(legendItems: self.legendItems) -// } if let error = error { self.presentAlert(error: error) } @@ -127,31 +122,36 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } legendGroup.notify(queue: .main) { [weak self] in guard let self = self else { return } - let symbols = self.legendInfos + [self.boundingBoxSymbol, self.attachmentSymbol, self.connectivitySymbol] - self.makeSwatches(legend: symbols) { legendItems in - self.symbolsDataSource = SymbolsDataSource(legendItems: legendItems) + let featureLayerSymbols = self.legendInfos.reduce(into: [(String, AGSSymbol)]() ) { specifiedSymbols, legendInfo in + if !legendInfo.name.isEmpty, let symbol = legendInfo.symbol { + specifiedSymbols.append((legendInfo.name, symbol)) + } + } + let allSymbols: [(String, AGSSymbol)] = featureLayerSymbols + + [("Bounding box", self.boundingBoxSymbol.symbol), + ("Attachment", self.attachmentSymbol.symbol), + ("Connectivity", self.connectivitySymbol.symbol)] + self.makeSwatches(legend: allSymbols) { legendItems in + self.symbolsDataSource = SymbolsDataSource(legendItems: legendItems.sorted { $0.name < $1.name }) } } } - private func makeSwatches(legend: [Any], completion: @escaping ([LegendItem]) -> Void) { + /// Create swatches from the provided symbols. + /// + /// - Parameters: + /// - legend: The array containing all of the symbols and their names. + /// - completion: A closure to pass back the legend with cached images. + private func makeSwatches(legend: [(String, AGSSymbol)], completion: @escaping ([LegendItem]) -> Void) { let swatchGroup = DispatchGroup() var legendItems = [LegendItem]() - var symbol = AGSSymbol() - var name = String() legend.forEach { symbolItem in - if let legendInfoItem = symbolItem as? AGSLegendInfo, !legendInfoItem.name.isEmpty { - name = legendInfoItem.name - symbol = legendInfoItem.symbol! - } else if let containerViewSymbol = symbolItem as? ContainerViewSymbol { - name = containerViewSymbol.name - symbol = containerViewSymbol.symbol - } + let symbol = symbolItem.1 swatchGroup.enter() - symbol.createSwatch(withBackgroundColor: nil, screen: .main) { (image, error) in + symbol.createSwatch(withBackgroundColor: nil, screen: .main) { image, _ in if let image = image { defer { swatchGroup.leave() } - legendItems.append(LegendItem(name: name, image: image)) + legendItems.append(LegendItem(name: symbolItem.0, image: image)) } else { swatchGroup.leave() } @@ -161,8 +161,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS completion(legendItems) } } - - func makeSwatch(name: String, symbol: AGSSymbol) -> /// Get the container feature that was tapped on. /// @@ -252,7 +250,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.setViewpointGeometry(geometry) { [weak self] _ in guard let self = self else { return } // Get the associations for this extent to display how content features are attached or connected. - self.utilityNetwork?.associations(withExtent: self.graphicsOverlay.extent) { (containmentAssociations, error) in + self.utilityNetwork?.associations(withExtent: self.graphicsOverlay.extent) { containmentAssociations, _ in guard let containmentAssociations = containmentAssociations else { return } containmentAssociations.forEach { association in var symbol = AGSSymbol() @@ -286,28 +284,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } - /// Create a swatch from the provided symbol. - /// - /// - Parameter symbol: The symbol to make a swatch from. - /// - Returns The resulting image that represents the swatch. -// func makeSwatch(symbol: AGSSymbol) -> UIImage { -// let swatchGroup = DispatchGroup() -// var swatchImage = UIImage() -// swatchGroup.enter() -// DispatchQueue.global(qos: .userInitiated).async { -// symbol.createSwatch(withBackgroundColor: nil, screen: .main) { [weak self] (image, error) in -// if let image = image { -// swatchImage = image -// } else if let error = error { -// self?.presentAlert(error: error) -// } -// swatchGroup.leave() -// } -// } -// swatchGroup.wait() -// return swatchImage -// } - // MARK: - UIViewController override func viewDidLoad() { @@ -323,32 +299,21 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // MARK: - Navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "DisplayContentLegendSegue", let controller = segue.destination as? UITableViewController { controller.presentationController?.delegate = self controller.tableView.dataSource = symbolsDataSource } -// as! DisplayContentUtilityNetworkTableViewController -// controller.presentationController?.delegate = self -// controller.legendInfos = legendInfos -// controller.contentSwatches = [ -// "Bounding box": makeSwatch(symbol: boundingBoxSymbol), -// "Attachment": makeSwatch(symbol: attachmentSymbol), -// "Connectivity": makeSwatch(symbol: connectivitySymbol) -// ] -// controller.images = images -// } } // MARK: - UIAdaptivePresentationControllerDelegate - func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { return .none } } +// MARK: - AGSAuthenticationManagerDelegate extension DisplayContentUtilityNetworkContainerViewController: AGSAuthenticationManagerDelegate { func authenticationManager(_ authenticationManager: AGSAuthenticationManager, didReceive challenge: AGSAuthenticationChallenge) { // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. From 08063f4cc13364b6bf8aae4e4f9d6834ef229364 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 9 Apr 2021 16:54:08 -0700 Subject: [PATCH 039/109] Removed table view controller file --- .../project.pbxproj | 6 -- ...entUtilityNetworkTableViewController.swift | 58 ------------------- 2 files changed, 64 deletions(-) delete mode 100644 arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index f8a6f2d88..5f17f37ff 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -839,7 +839,6 @@ F15CF0C923EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15CF0C823EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift */; }; F15CF0CB23EE27F00038F052 /* DisplaySubtypeFeatureLayer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F15CF0CA23EE27F00038F052 /* DisplaySubtypeFeatureLayer.storyboard */; }; F15CF0CC23EE31A70038F052 /* DisplaySubtypeFeatureLayerViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F15CF0C823EE273A0038F052 /* DisplaySubtypeFeatureLayerViewController.swift */; }; - F16174B02602E55A00300FF9 /* DisplayContentUtilityNetworkTableViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */; }; F164997622E90F150088CA93 /* FeatureLayerDictionaryRendererViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1F62C4122E6560C00EFD599 /* FeatureLayerDictionaryRendererViewController.swift */; }; F164997922E924C40088CA93 /* EditAndSyncFeatures.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F164997822E924C40088CA93 /* EditAndSyncFeatures.storyboard */; }; F164997B22E924F40088CA93 /* EditAndSyncFeaturesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F164997A22E924F40088CA93 /* EditAndSyncFeaturesViewController.swift */; }; @@ -851,7 +850,6 @@ F1710AF325EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */; }; F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */; }; F17961A124DA3A27006FE7C1 /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1124F0B24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift */; }; - F1841C6725F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */; }; F1987CFD23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; F1987CFF23F7321400DF41CC /* FindClosestFacilityInteractiveViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */; }; F1987D0023F7325300DF41CC /* FindClosestFacilityInteractive.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1987CFE23F7314000DF41CC /* FindClosestFacilityInteractive.storyboard */; }; @@ -946,7 +944,6 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( - F16174B02602E55A00300FF9 /* DisplayContentUtilityNetworkTableViewController.swift in CopyFiles */, F1710AF525EEF4C000900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift in CopyFiles */, 009B600325E5DB4700BB9A77 /* CreateSymbolStylesFromWebStylesViewController.swift in CopyFiles */, 0023F98825E717EA006B574E /* SimulatedNMEADataSource.swift in CopyFiles */, @@ -1828,7 +1825,6 @@ F16922B425158B4400A8F36E /* EditKMLGroundOverlayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditKMLGroundOverlayViewController.swift; sourceTree = ""; }; F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayContentUtilityNetworkContainerViewController.swift; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift"; sourceTree = SOURCE_ROOT; }; F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = DisplayContentUtilityNetworkContainer.storyboard; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkContainer.storyboard"; sourceTree = SOURCE_ROOT; }; - F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayContentUtilityNetworkTableViewController.swift; path = "arcgis-ios-sdk-samples/Utility Network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift"; sourceTree = SOURCE_ROOT; }; F1987CFC23F7313E00DF41CC /* FindClosestFacilityInteractiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindClosestFacilityInteractiveViewController.swift; sourceTree = ""; }; F1987CFE23F7314000DF41CC /* FindClosestFacilityInteractive.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = FindClosestFacilityInteractive.storyboard; sourceTree = ""; }; F1987D0223F7677E00DF41CC /* DisplaySubtypeSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySubtypeSettingsViewController.swift; sourceTree = ""; }; @@ -4536,7 +4532,6 @@ isa = PBXGroup; children = ( F1710AEF25EECFDD00900FF2 /* DisplayContentUtilityNetworkContainerViewController.swift */, - F1841C6625F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift */, F1710AF225EED01600900FF2 /* DisplayContentUtilityNetworkContainer.storyboard */, ); path = "Display content of utility network container"; @@ -5239,7 +5234,6 @@ 3ED75D041ED39EDF009B1F75 /* FindServiceAreaInteractiveViewController.swift in Sources */, 3E4BF4441C5AEA6500D85919 /* WorldAddressesViewController.swift in Sources */, 9DE9FE3422FDB7CA00142DE1 /* LocationHistoryViewController.swift in Sources */, - F1841C6725F82DF50051892D /* DisplayContentUtilityNetworkTableViewController.swift in Sources */, 3ED028EF1B8E3AA500ACA70D /* FeatureLayerSelectionViewController.swift in Sources */, 3E5E09401EF4567A00FF3454 /* RelatedFeaturesViewController.swift in Sources */, D97B7E3C1FD9BE2B00E1239D /* SymbolizeShapefileViewController.swift in Sources */, diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift deleted file mode 100644 index 388b45c00..000000000 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkTableViewController.swift +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021 Esri -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import UIKit -import ArcGIS - -class DisplayContentUtilityNetworkTableViewController: UITableViewController { - var legendInfos = [AGSLegendInfo]() - var contentSwatches = KeyValuePairs() - var images = [(String, UIImage)]() - - // Set the number of rows. - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return legendInfos.count + contentSwatches.count - } - - // Set the number of sections. - override func numberOfSections(in tableView: UITableView) -> Int { - 1 - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "DisplayContentLegendCell", for: indexPath) - // Add the container view swatches to the legend after the feature layer legend information. -// if indexPath.row >= legendInfos.count { -// let contentSwatch = indexPath.row - legendInfos.count -// cell.textLabel?.text = contentSwatches[contentSwatch].key -// cell.imageView?.image = contentSwatches[contentSwatch].value -// cell.setNeedsLayout() -// } else { -// // Add the information provided by the feature layers to the legend. -// let legendInfo = legendInfos[indexPath.row] -// cell.textLabel?.text = legendInfo.name -// legendInfo.symbol?.createSwatch { (image, _) in -// cell.imageView?.image = image -// cell.setNeedsLayout() -// } -// } - cell.textLabel?.text = images[indexPath.row].0 - cell.imageView?.image = images[indexPath.row].1 - return cell - } - - override func viewDidLoad() { - super.viewDidLoad() - } -} From affe0a6a5a61ab5e340a7ed902285e29ab59ab7b Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 9 Apr 2021 17:28:44 -0700 Subject: [PATCH 040/109] Fixed viewpoint in exit container view --- ...DisplayContentUtilityNetworkContainerViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index a1f8565ff..ee3a881b6 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -68,9 +68,10 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS (mapView.map?.operationalLayers as? [AGSLayer])?.forEach { layer in // Make each operational layer visible. layer.isVisible = true - guard let previousViewpoint = previousViewpoint else { return } + } + if let previousViewpoint = previousViewpoint { // Return to the viewpoint before container view was entered. - mapView.setViewpointGeometry(previousViewpoint.targetGeometry) { [weak self] _ in + mapView.setViewpoint(previousViewpoint) { [weak self] _ in // Enable interaction on the map view. self?.mapView.isUserInteractionEnabled = true } From 0a50ddbabc27257c34dfeba5fd6d0e319dac14bb Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 9 Apr 2021 17:31:40 -0700 Subject: [PATCH 041/109] Removed table view from metadata --- .../README.metadata.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json index a0ed6e36e..678c9df5e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.metadata.json @@ -28,8 +28,7 @@ "AGSUtilityNetworkDefinition" ], "snippets": [ - "DisplayContentUtilityNetworkContainerViewController.swift", - "DisplayContentUtilityNetworkTableViewController.swift" + "DisplayContentUtilityNetworkContainerViewController.swift" ], "title": "Display content of utility network container" } From 08e31d202d434b70e056a1f989564519f1d2df0a Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 12 Apr 2021 16:11:58 -0700 Subject: [PATCH 042/109] Updated credentials --- .../DisplayContentUtilityNetworkContainerViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index ee3a881b6..8771ca8fb 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -318,7 +318,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS extension DisplayContentUtilityNetworkContainerViewController: AGSAuthenticationManagerDelegate { func authenticationManager(_ authenticationManager: AGSAuthenticationManager, didReceive challenge: AGSAuthenticationChallenge) { // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. - let credentials = AGSCredential(user: "editor01", password: "S7#i2LWmYH75") + let credentials = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") challenge.continue(with: credentials) } } From 028aa3aa1614eb3f61111c24b3af27064f6b06e6 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Mon, 12 Apr 2021 16:49:57 -0700 Subject: [PATCH 043/109] Update the sample to use new API. --- arcgis-ios-sdk-samples/Info.plist | 4 ++ ...viceLocationWithNMEADataSources.storyboard | 26 +++++++++++- ...ionWithNMEADataSourcesViewController.swift | 40 +++++++++++++++++-- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/arcgis-ios-sdk-samples/Info.plist b/arcgis-ios-sdk-samples/Info.plist index e9334e45c..41a20a95c 100644 --- a/arcgis-ios-sdk-samples/Info.plist +++ b/arcgis-ios-sdk-samples/Info.plist @@ -115,6 +115,10 @@ + UISupportedExternalAccessoryProtocols + + com.bad-elf.gps + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard index 0dc09f12b..75a3e4cd0 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard @@ -19,7 +19,7 @@ - + @@ -62,6 +62,24 @@ + + + + + + + + + + + + + + + + + + @@ -70,11 +88,14 @@ - + + + + @@ -82,6 +103,7 @@ + diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift index 95ebbbe0e..30309ab9c 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift @@ -32,11 +32,20 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { @IBOutlet var recenterBarButtonItem: UIBarButtonItem! /// The button to reset the demo. @IBOutlet var resetBarButtonItem: UIBarButtonItem! + /// The segmented control to toggle between mock data and real device. + @IBOutlet var segmentedControl: UISegmentedControl! + + // MARK: Constants + + /// The name of the BadElf device to identify it from accessories list. + let surveyorName = "Bad Elf GNSS Surveyor" + /// The protocol string to establish the EASession. + let protocolName = "com.bad-elf.gps" // MARK: Instance properties /// An NMEA location data source, to parse NMEA data. - let nmeaLocationDataSource = AGSNMEALocationDataSource(receiverSpatialReference: .wgs84()) + var nmeaLocationDataSource: AGSNMEALocationDataSource! /// A mock data source to read NMEA sentences from a local file, and generate /// mock NMEA data every fixed amount of time. let mockNMEADataSource = SimulatedNMEADataSource(nmeaSourceFile: Bundle.main.url(forResource: "Redlands", withExtension: "nmea")!, speed: 1.5) @@ -47,6 +56,7 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { // Set buttons states. startBarButtonItem.isEnabled = false resetBarButtonItem.isEnabled = true + segmentedControl.isEnabled = false // Set NMEA location data source for location display. mapView.locationDisplay.dataSource = nmeaLocationDataSource // Start the data source and location display. @@ -71,6 +81,7 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { // Reset buttons states. startBarButtonItem.isEnabled = true resetBarButtonItem.isEnabled = false + segmentedControl.isEnabled = true // Reset the status text. statusLabel.text = "Satellites info will be shown here." // Reset and stop the location display. @@ -81,6 +92,29 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { mockNMEADataSource.stop() } + @IBAction func segmentedControlValueChanged(_ sender: UISegmentedControl) { + switch sender.selectedSegmentIndex { + case 0: + nmeaLocationDataSource = AGSNMEALocationDataSource(receiverSpatialReference: .wgs84()) + nmeaLocationDataSource.locationChangeHandlerDelegate = self + mockNMEADataSource.delegate = self + case 1: + mockNMEADataSource.delegate = nil + if let accessory = EAAccessoryManager.shared().connectedAccessories.first(where: { $0.name == surveyorName }), + let dataSource = AGSNMEALocationDataSource(eaAccessory: accessory, protocol: protocolName) { + nmeaLocationDataSource = dataSource + nmeaLocationDataSource.locationChangeHandlerDelegate = self + } else { + // Reset to simulated data if no real device found. + presentAlert(message: "GNSS surveyor not found!") + sender.selectedSegmentIndex = 0 + segmentedControlValueChanged(sender) + } + default: + return + } + } + // MARK: UIViewController override func viewDidLoad() { @@ -90,10 +124,8 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { "DisplayDeviceLocationWithNMEADataSourcesViewController", "SimulatedNMEADataSource" ] - // Load NMEA location data source. startBarButtonItem.isEnabled = true - nmeaLocationDataSource.locationChangeHandlerDelegate = self - mockNMEADataSource.delegate = self + segmentedControlValueChanged(segmentedControl) } override func viewWillDisappear(_ animated: Bool) { From 18d5cf2147ebcac865b699bd5ff29c6551c5e65e Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 13 Apr 2021 14:56:56 -0700 Subject: [PATCH 044/109] Add EOS and SXBlue support. --- arcgis-ios-sdk-samples/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arcgis-ios-sdk-samples/Info.plist b/arcgis-ios-sdk-samples/Info.plist index 41a20a95c..6438772f9 100644 --- a/arcgis-ios-sdk-samples/Info.plist +++ b/arcgis-ios-sdk-samples/Info.plist @@ -118,6 +118,8 @@ UISupportedExternalAccessoryProtocols com.bad-elf.gps + com.eos-gnss.positioningsource + com.geneq.sxbluegpssource UISupportedInterfaceOrientations From 1a6b94d3a2b62ecc7e96697eb859da854782894d Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 13 Apr 2021 16:31:33 -0700 Subject: [PATCH 045/109] Update source code and storyboard. --- ...viceLocationWithNMEADataSources.storyboard | 34 +----- ...ionWithNMEADataSourcesViewController.swift | 104 ++++++++++-------- 2 files changed, 67 insertions(+), 71 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard index 75a3e4cd0..15b3abdde 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard @@ -19,7 +19,7 @@ - + @@ -43,12 +43,12 @@ - + - + - + @@ -62,24 +62,6 @@ - - - - - - - - - - - - - - - - - - @@ -88,14 +70,11 @@ - - - + - @@ -103,8 +82,7 @@ - - + diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift index 30309ab9c..fde3be25c 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift @@ -26,39 +26,80 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { } /// The label to display satellites info. @IBOutlet var statusLabel: UILabel! - /// The button to start the demo. - @IBOutlet var startBarButtonItem: UIBarButtonItem! + /// The button to choose a data source and start the demo. + @IBOutlet var sourceBarButtonItem: UIBarButtonItem! /// The button to reset pan mode to "recenter". @IBOutlet var recenterBarButtonItem: UIBarButtonItem! /// The button to reset the demo. @IBOutlet var resetBarButtonItem: UIBarButtonItem! - /// The segmented control to toggle between mock data and real device. - @IBOutlet var segmentedControl: UISegmentedControl! // MARK: Constants - /// The name of the BadElf device to identify it from accessories list. - let surveyorName = "Bad Elf GNSS Surveyor" - /// The protocol string to establish the EASession. - let protocolName = "com.bad-elf.gps" + /// The protocols specified in the `Info.plist` that the app uses to + /// communicate with external accessory hardware. + let supportedProtocolStrings: [String] = { + guard let protocols = Bundle.main.object(forInfoDictionaryKey: "UISupportedExternalAccessoryProtocols") as? [String] else { + return [] + } + return protocols + }() // MARK: Instance properties /// An NMEA location data source, to parse NMEA data. - var nmeaLocationDataSource: AGSNMEALocationDataSource! + var nmeaLocationDataSource: AGSNMEALocationDataSource? /// A mock data source to read NMEA sentences from a local file, and generate /// mock NMEA data every fixed amount of time. let mockNMEADataSource = SimulatedNMEADataSource(nmeaSourceFile: Bundle.main.url(forResource: "Redlands", withExtension: "nmea")!, speed: 1.5) // MARK: Actions - @IBAction func start() { + @IBAction func chooseDataSource(_ sender: UIBarButtonItem) { + let alertController = UIAlertController( + title: "Choose an NMEA data source.", + message: nil, + preferredStyle: .actionSheet + ) + // Populate from connected GNSS surveyor devices. + EAAccessoryManager.shared().connectedAccessories.forEach { accessory in + // The protocol string to establish the EASession. + guard let protocolString = accessory.protocolStrings.first(where: { supportedProtocolStrings.contains($0) }) else { + // Skip any device which protocol is not included in the plist. + // This typically shouldn't happen, unless the device requires + // additional configuration. + return + } + let action = UIAlertAction(title: accessory.name, style: .default) { [self] _ in + nmeaLocationDataSource = AGSNMEALocationDataSource(eaAccessory: accessory, protocol: protocolString) + nmeaLocationDataSource?.locationChangeHandlerDelegate = self + start() + } + alertController.addAction(action) + } + // Add mock data source to the options. + let mockDataSourceAction = UIAlertAction(title: "Mock Data", style: .default) { [self] _ in + nmeaLocationDataSource = AGSNMEALocationDataSource(receiverSpatialReference: .wgs84()) + nmeaLocationDataSource!.locationChangeHandlerDelegate = self + mockNMEADataSource.delegate = self + start() + } + alertController.addAction(mockDataSourceAction) + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) + alertController.addAction(cancelAction) + alertController.popoverPresentationController?.barButtonItem = sender + present(alertController, animated: true) + } + + func start() { + guard let dataSource = nmeaLocationDataSource else { + presentAlert(title: "Error", message: "NMEA data source failed to initialize from GNSS surveyor!") + return + } + // Set NMEA location data source for location display. + mapView.locationDisplay.dataSource = dataSource // Set buttons states. - startBarButtonItem.isEnabled = false + sourceBarButtonItem.isEnabled = false resetBarButtonItem.isEnabled = true - segmentedControl.isEnabled = false - // Set NMEA location data source for location display. - mapView.locationDisplay.dataSource = nmeaLocationDataSource // Start the data source and location display. mockNMEADataSource.start() mapView.locationDisplay.start() @@ -79,9 +120,8 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { @IBAction func reset() { // Reset buttons states. - startBarButtonItem.isEnabled = true resetBarButtonItem.isEnabled = false - segmentedControl.isEnabled = true + sourceBarButtonItem.isEnabled = true // Reset the status text. statusLabel.text = "Satellites info will be shown here." // Reset and stop the location display. @@ -90,29 +130,8 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { mapView.locationDisplay.stop() // Pause the mock data generation. mockNMEADataSource.stop() - } - - @IBAction func segmentedControlValueChanged(_ sender: UISegmentedControl) { - switch sender.selectedSegmentIndex { - case 0: - nmeaLocationDataSource = AGSNMEALocationDataSource(receiverSpatialReference: .wgs84()) - nmeaLocationDataSource.locationChangeHandlerDelegate = self - mockNMEADataSource.delegate = self - case 1: - mockNMEADataSource.delegate = nil - if let accessory = EAAccessoryManager.shared().connectedAccessories.first(where: { $0.name == surveyorName }), - let dataSource = AGSNMEALocationDataSource(eaAccessory: accessory, protocol: protocolName) { - nmeaLocationDataSource = dataSource - nmeaLocationDataSource.locationChangeHandlerDelegate = self - } else { - // Reset to simulated data if no real device found. - presentAlert(message: "GNSS surveyor not found!") - sender.selectedSegmentIndex = 0 - segmentedControlValueChanged(sender) - } - default: - return - } + // Disconnect from the mock data updates. + mockNMEADataSource.delegate = nil } // MARK: UIViewController @@ -124,8 +143,7 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { "DisplayDeviceLocationWithNMEADataSourcesViewController", "SimulatedNMEADataSource" ] - startBarButtonItem.isEnabled = true - segmentedControlValueChanged(segmentedControl) + sourceBarButtonItem.isEnabled = true } override func viewWillDisappear(_ animated: Bool) { @@ -139,8 +157,8 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { extension DisplayDeviceLocationWithNMEADataSourcesViewController: SimulatedNMEADataSourceDelegate { func dataSource(_ dataSource: SimulatedNMEADataSource, didUpdate nmeaData: Data) { // Push mock data into the data source. - // Note: You can also get real-time NMEA sentences from a GPS dongle. - nmeaLocationDataSource.push(nmeaData) + // Note: You can also get real-time NMEA sentences from a GNSS surveyor. + nmeaLocationDataSource?.push(nmeaData) } } From e06b327425913a36642b07643117aa796f9a5093 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 13 Apr 2021 17:05:53 -0700 Subject: [PATCH 046/109] Update source code. --- ...viceLocationWithNMEADataSources.storyboard | 2 +- ...ionWithNMEADataSourcesViewController.swift | 44 +++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard index 15b3abdde..d4be8a583 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard @@ -24,7 +24,7 @@ -
c|W)17Bc;n>sOX5nfxk1vmh~wO&Wb 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%0AVjw|1|(qT*y)!ZUu7vm*8HY5Om}PWAI3T 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 FV1iN`UB3VT literal 30505 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 From 0b80af9a73160d9b4942b423ab86d95a79b186bf Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Wed, 14 Apr 2021 15:09:34 -0700 Subject: [PATCH 048/109] Rephrase GNSS. --- .../README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index 53690eebb..a8e907f9c 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -6,9 +6,9 @@ Parse NMEA sentences and use the results to show device location on the map. ## Use case -NMEA sentences can be retrieved from GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GPS receiver can retrieve NMEA sentences by using a separate GPS dongle, commonly connected Bluetooth or through a serial port. +NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GNSS receiver can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected Bluetooth or through a serial port. -The NMEA location data source allows for detailed interrogation of the information coming from the GPS receiver. For example, allowing you to report the number of satellites in view. +The NMEA location data source allows for detailed interrogation of the information coming from the GNSS receiver. For example, allowing you to report the number of satellites in view. ## How to use the sample @@ -34,7 +34,7 @@ Tap "Source" to choose between a simulated location data source and any data sou ## About the data -A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically, and allows the sample to be used on devices without a GPS dongle that produces NMEA data. +A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically, and allows the sample to be used on devices without a GNSS dongle that produces NMEA data. The route taken in this sample features a [2-minute driving trip around Redlands, CA](https://arcgis.com/home/item.html?id=d5bad9f4fee9483791e405880fb466da). From 2c467a0737b8cde9d2dbc204174acf92b83cf3d6 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Wed, 14 Apr 2021 15:21:40 -0700 Subject: [PATCH 049/109] Rephrase README. --- .../README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index a8e907f9c..24d18ba36 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -8,20 +8,20 @@ Parse NMEA sentences and use the results to show device location on the map. NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GNSS receiver can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected Bluetooth or through a serial port. -The NMEA location data source allows for detailed interrogation of the information coming from the GNSS receiver. For example, allowing you to report the number of satellites in view. +The NMEA location data source allows for detailed interrogation of the information coming from the GNSS receiver. For example, allowing you to report the number of satellites in view, accuracy of the location, etc. ## How to use the sample -Tap "Source" to choose between a simulated location data source and any data source created from a connected GNSS device, and initiate the location display. Tap "Recenter" to recenter the location display. Tap "Reset" to reset the location display and location data source. +Tap "Source" to choose between a simulated location data source or any data source created from a connected GNSS device, and initiate the location display. Tap "Recenter" to recenter the location display. Tap "Reset" to reset the location display and location data source. ## How it works 1. Load NMEA sentences. - * If a supported GNSS surveyor is connected, the sample can get NMEA updates from it. + * If a supported GNSS receiver is connected, the sample can get NMEA updates from it. * Otherwise, the sample will read mock data from a local file. -2. Create an `AGSNMEALocationDataSource`. There are 2 methods to provide updates to the data source. +2. Create an `AGSNMEALocationDataSource`. There are 2 ways to provide updates to the data source. * When updates are received from a GNSS device or the mock data provider, push the data into `AGSNMEALocationDataSource`. - * In the Runtime SDK 100.11.0 release, it is also supported to create an `AGSNMEALocationDataSource` with the GNSS device connected via `EAAccessory` and its protocol listed in `UISupportedExternalAccessoryProtocols`. + * In the Runtime SDK 100.11.0 release, it is also supported to create an `AGSNMEALocationDataSource` with the GNSS device connected via `EAAccessory` and its protocol specified in `UISupportedExternalAccessoryProtocols`. The data source created this way will automatically get updates from the device instead of requiring to push data explicitly. 3. Set the `AGSNMEALocationDataSource` to the location display's data source. 4. Start the location display to begin receiving location and satellite updates. @@ -34,7 +34,7 @@ Tap "Source" to choose between a simulated location data source and any data sou ## About the data -A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically, and allows the sample to be used on devices without a GNSS dongle that produces NMEA data. +A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically, and allows the sample to be used on devices without a GNSS receiver that produces NMEA data. The route taken in this sample features a [2-minute driving trip around Redlands, CA](https://arcgis.com/home/item.html?id=d5bad9f4fee9483791e405880fb466da). @@ -46,7 +46,7 @@ To support GNSS device connection in an app, here are a few steps: * Refer to the device manufacturer's documentation to get its protocol string, and add the protocol to the app’s `Info.plist` under the key `UISupportedExternalAccessoryProtocols`. * When working with any MFi accessory, the end user must register their iOS app with the accessory manufacturer first to whitelist their app before submitting it to the AppStore for approval. This is a requirement by Apple and stated in the iOS Developer Program License Agreement. -Please read Apples documentation below for further details. +Please read Apple's documentation below for further details. * [`EAAccessory`](https://developer.apple.com/documentation/externalaccessory) * [`UISupportedExternalAccessoryProtocols`](https://developer.apple.com/documentation/bundleresources/information_property_list/uisupportedexternalaccessoryprotocols) From 362ced3af4eb9a75412c0e21c52e4dd840d38a67 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Wed, 14 Apr 2021 15:23:37 -0700 Subject: [PATCH 050/109] Fix section header. --- .../Display device location with NMEA data sources/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index 24d18ba36..01816a95b 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -38,7 +38,7 @@ A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` objec The route taken in this sample features a [2-minute driving trip around Redlands, CA](https://arcgis.com/home/item.html?id=d5bad9f4fee9483791e405880fb466da). -## Additional Information +## Additional information To support GNSS device connection in an app, here are a few steps: From ac83018f6641b936ad531ce5fb0bef6e29585ef7 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Wed, 14 Apr 2021 17:22:53 -0700 Subject: [PATCH 051/109] Addressed review comments --- .../Content Display Logic/ContentPList.plist | 6 +-- ...tilityNetworkContainerViewController.swift | 40 ++++++++----------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist index 3eeb58132..5378351ee 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist +++ b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist @@ -1835,9 +1835,9 @@ Create a simple electric distribution report that displays the count of customers and total load per phase by tracing downstream from a given point. storyboardName CreateLoadReport - - - displayName + + + displayName Display content of utility network container storyboardName DisplayContentUtilityNetworkContainer diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 8771ca8fb..215c015bd 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -19,7 +19,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// The map view managed by the view controller. @IBOutlet var mapView: AGSMapView! { didSet { - AGSAuthenticationManager.shared().delegate = self makeMap() mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) } @@ -30,7 +29,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// A feature service for an electric utility network in Naperville, Illinois. let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! - var utilityNetwork: AGSUtilityNetwork? + var utilityNetwork: AGSUtilityNetwork! let graphicsOverlay = AGSGraphicsOverlay() /// The default or previous viewpoint before entering the container view. var previousViewpoint: AGSViewpoint? @@ -53,11 +52,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS ) /// The data source for the legend table. - private var symbolsDataSource: SymbolsDataSource? { - didSet { - legendBarButtonItem.isEnabled = true - } - } + private var symbolsDataSource: SymbolsDataSource? /// The action that is prompted when exiting the container view. @IBAction func exitContainerView() { @@ -112,20 +107,20 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS featureLayers.forEach { layer in legendGroup.enter() // Get the legend information of each layer. - layer.fetchLegendInfos { [weak self] (legendInfos, error) in - guard let self = self, let legendInfos = legendInfos else { return } + layer.fetchLegendInfos { [weak self] legendInfos, _ in defer { legendGroup.leave() } - self.legendInfos.append(contentsOf: legendInfos) - if let error = error { - self.presentAlert(error: error) - } + guard let legendInfos = legendInfos else { return } + self?.legendInfos.append(contentsOf: legendInfos) } } legendGroup.notify(queue: .main) { [weak self] in guard let self = self else { return } - let featureLayerSymbols = self.legendInfos.reduce(into: [(String, AGSSymbol)]() ) { specifiedSymbols, legendInfo in - if !legendInfo.name.isEmpty, let symbol = legendInfo.symbol { - specifiedSymbols.append((legendInfo.name, symbol)) + let featureLayerSymbols: [(String, AGSSymbol)] = self.legendInfos.compactMap { legendInfo in + if !legendInfo.name.isEmpty, + let symbol = legendInfo.symbol { + return (legendInfo.name, symbol) + } else { + return nil } } let allSymbols: [(String, AGSSymbol)] = featureLayerSymbols + @@ -134,6 +129,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS ("Connectivity", self.connectivitySymbol.symbol)] self.makeSwatches(legend: allSymbols) { legendItems in self.symbolsDataSource = SymbolsDataSource(legendItems: legendItems.sorted { $0.name < $1.name }) + self.legendBarButtonItem.isEnabled = true } } } @@ -150,12 +146,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let symbol = symbolItem.1 swatchGroup.enter() symbol.createSwatch(withBackgroundColor: nil, screen: .main) { image, _ in - if let image = image { - defer { swatchGroup.leave() } - legendItems.append(LegendItem(name: symbolItem.0, image: image)) - } else { - swatchGroup.leave() - } + defer { swatchGroup.leave() } + guard let image = image else { return } + legendItems.append(LegendItem(name: symbolItem.0, image: image)) } } swatchGroup.notify(queue: .main) { @@ -289,6 +282,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS override func viewDidLoad() { super.viewDidLoad() + AGSAuthenticationManager.shared().delegate = self // Load the utility network. loadUtilityNetwork() // Add a graphics overlay. @@ -296,7 +290,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Get the legends from the feature service. fetchLegendInfo() // Add the source code button item to the right of navigation bar. - (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainerViewController", "DisplayContentUtilityNetworkTableViewController"] + (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DisplayContentUtilityNetworkContainerViewController"] } // MARK: - Navigation From 2c5347caeb4550735e6624d749bedbc3612875ba Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 15 Apr 2021 15:41:24 -0700 Subject: [PATCH 052/109] Removed escaping closure --- ...playContentUtilityNetworkContainerViewController.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 215c015bd..19493d72f 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -161,12 +161,12 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// - Parameters: /// - layerResults: The layer results identified by the touch delegate. /// - completion: A closure to pass back the feature that was tapped on. - func identifyContainerFeature(layerResults: [AGSIdentifyLayerResult], completion: @escaping (AGSArcGISFeature) -> Void) { + func identifyContainerFeature(layerResults: [AGSIdentifyLayerResult]) { // A map containing SubtypeFeatureLayer is expected to have features as part of its sublayer's result. let layerResult = layerResults.first(where: { $0.layerContent is AGSSubtypeFeatureLayer }) layerResult?.sublayerResults.forEach { sublayerResult in guard let feature = sublayerResult.geoElements.first(where: { $0 is AGSArcGISFeature }) as? AGSArcGISFeature else { return } - completion(feature) + addElementAssociations(for: feature) } } @@ -269,9 +269,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } if let layerResults = layerResults { - self.identifyContainerFeature(layerResults: layerResults) { containerFeature in - self.addElementAssociations(for: containerFeature) - } + self.identifyContainerFeature(layerResults: layerResults) } else if let error = error { self.presentAlert(error: error) } From 75b5f68c368d5706d707b01c05ad687d712f157c Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Fri, 16 Apr 2021 11:06:04 -0700 Subject: [PATCH 053/109] Apply suggestions from code review Co-authored-by: Vivian Quach --- .../README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index 01816a95b..e93a5b912 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -6,7 +6,7 @@ Parse NMEA sentences and use the results to show device location on the map. ## Use case -NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GNSS receiver can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected Bluetooth or through a serial port. +NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GNSS receiver can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected through Bluetooth or a serial port. The NMEA location data source allows for detailed interrogation of the information coming from the GNSS receiver. For example, allowing you to report the number of satellites in view, accuracy of the location, etc. @@ -21,7 +21,7 @@ Tap "Source" to choose between a simulated location data source or any data sour * Otherwise, the sample will read mock data from a local file. 2. Create an `AGSNMEALocationDataSource`. There are 2 ways to provide updates to the data source. * When updates are received from a GNSS device or the mock data provider, push the data into `AGSNMEALocationDataSource`. - * In the Runtime SDK 100.11.0 release, it is also supported to create an `AGSNMEALocationDataSource` with the GNSS device connected via `EAAccessory` and its protocol specified in `UISupportedExternalAccessoryProtocols`. The data source created this way will automatically get updates from the device instead of requiring to push data explicitly. + * With the Runtime SDK 100.11.0 release, you can create an `AGSNMEALocationDataSource` with the GNSS device connected via `EAAccessory` and its protocol specified in `UISupportedExternalAccessoryProtocols`. The data source created this way will automatically get updates from the device instead of requiring to push data explicitly. 3. Set the `AGSNMEALocationDataSource` to the location display's data source. 4. Start the location display to begin receiving location and satellite updates. @@ -34,7 +34,7 @@ Tap "Source" to choose between a simulated location data source or any data sour ## About the data -A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically, and allows the sample to be used on devices without a GNSS receiver that produces NMEA data. +A list of NMEA sentences is used to initialize a `SimulatedNMEADataSource` object. This simulated data source provides NMEA data periodically and allows the sample to be used on devices without a GNSS receiver. The route taken in this sample features a [2-minute driving trip around Redlands, CA](https://arcgis.com/home/item.html?id=d5bad9f4fee9483791e405880fb466da). @@ -42,8 +42,8 @@ The route taken in this sample features a [2-minute driving trip around Redlands To support GNSS device connection in an app, here are a few steps: -* Enable Bluetooth connection in the Settings, or connect via Lightning connector. -* Refer to the device manufacturer's documentation to get its protocol string, and add the protocol to the app’s `Info.plist` under the key `UISupportedExternalAccessoryProtocols`. +* Enable Bluetooth connection in the device settings or connect via cable connection. +* Refer to the device manufacturer's documentation to get its protocol string and add the protocol to the app’s `Info.plist` under the `UISupportedExternalAccessoryProtocols` key. * When working with any MFi accessory, the end user must register their iOS app with the accessory manufacturer first to whitelist their app before submitting it to the AppStore for approval. This is a requirement by Apple and stated in the iOS Developer Program License Agreement. Please read Apple's documentation below for further details. From 09ced834ea5ec4f091139160b65dea8af3f46834 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 19 Apr 2021 16:44:01 -0700 Subject: [PATCH 054/109] Apply suggestions from code review Co-authored-by: Ting Chen --- .../DisplayContentUtilityNetworkContainerViewController.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 19493d72f..021f6c002 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -216,7 +216,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS self.graphicsOverlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } // The bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. - var boundingBox: AGSGeometry? if contentFeatures.count == 1, let point = (self.graphicsOverlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in @@ -225,7 +224,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS self.identifyAssociationsWithExtent(boundingBox: boundingBox) } } else { - boundingBox = AGSGeometryEngine.bufferGeometry(self.graphicsOverlay.extent, byDistance: 0.05) + let boundingBox = AGSGeometryEngine.bufferGeometry(self.graphicsOverlay.extent, byDistance: 0.05) self.identifyAssociationsWithExtent(boundingBox: boundingBox!) } } else if let error = error { From e4dc8f1075d1ab4089ced484bc708ba90c076815 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 19 Apr 2021 16:51:08 -0700 Subject: [PATCH 055/109] Fixed indentation and comment --- .../DisplayContentUtilityNetworkContainerViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 021f6c002..02b627d9d 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -52,7 +52,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS ) /// The data source for the legend table. - private var symbolsDataSource: SymbolsDataSource? + private var symbolsDataSource: SymbolsDataSource? /// The action that is prompted when exiting the container view. @IBAction func exitContainerView() { @@ -215,7 +215,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS let symbol = (content.featureTable as? AGSArcGISFeatureTable)?.layerInfo?.drawingInfo?.renderer?.symbol(for: content) self.graphicsOverlay.graphics.add(AGSGraphic(geometry: content.geometry, symbol: symbol)) } - // The bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. + // Set the bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. if contentFeatures.count == 1, let point = (self.graphicsOverlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in From 4e1bc56849d5109623d0e7167a516ebf74d9f1bb Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 19 Apr 2021 17:17:44 -0700 Subject: [PATCH 056/109] Shortened point variable --- .../DisplayContentUtilityNetworkContainerViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 02b627d9d..e9c833801 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -217,7 +217,7 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } // Set the bounding box which defines the container view may be computed using the extent of the features it contains or centered around its geometry at the container's view scale. if contentFeatures.count == 1, - let point = (self.graphicsOverlay.graphics.firstObject as? AGSGraphic)?.geometry as? AGSPoint { + let point = contentFeatures.first?.geometry as? AGSPoint { self.mapView.setViewpointCenter(point, scale: containerElement.assetType.containerViewScale) { _ in self.presentAlert(title: nil, message: "This feature contains no associations.") guard let boundingBox = self.mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry else { return } From 1991df3f8257868b85eeec4c80774486dc64fb00 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 19 Apr 2021 17:33:54 -0700 Subject: [PATCH 057/109] Updated user interaction --- ...layContentUtilityNetworkContainerViewController.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index e9c833801..28c9350f9 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -267,10 +267,13 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS // Identify the top most feature that corresponds to the tapped point. mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 5, returnPopupsOnly: false) { [weak self] (layerResults, error) in guard let self = self else { return } - if let layerResults = layerResults { + if let layerResults = layerResults, !layerResults.isEmpty { self.identifyContainerFeature(layerResults: layerResults) - } else if let error = error { - self.presentAlert(error: error) + } else { + if let error = error { + self.presentAlert(error: error) + } + self.mapView.isUserInteractionEnabled = true } } } From f7b53dad9ce036e37a6f09b4728b038b202ed6ad Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Tue, 20 Apr 2021 16:34:31 -0700 Subject: [PATCH 058/109] Updated readmes up to configure subnetwork trace --- .../Augmented reality/Collect data in AR/README.md | 2 +- .../ApplyMosaicRuleToRasters.storyboard | 4 ++-- .../Apply scheduled updates to preplanned map area/README.md | 2 +- .../Utility network/Configure subnetwork trace/README.md | 4 ++++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arcgis-ios-sdk-samples/Augmented reality/Collect data in AR/README.md b/arcgis-ios-sdk-samples/Augmented reality/Collect data in AR/README.md index 468fdf6a5..172d57591 100644 --- a/arcgis-ios-sdk-samples/Augmented reality/Collect data in AR/README.md +++ b/arcgis-ios-sdk-samples/Augmented reality/Collect data in AR/README.md @@ -51,7 +51,7 @@ This sample only uses the `arScreenToLocation` approach, as it is the only way t Note that unlike other scene samples, a basemap isn't shown most of the time, because the real world provides the context. Only while calibrating is the basemap displayed at 50% opacity, to give the user a visual reference to compare to. -**Real-scale AR** is one of three main patterns for working with geographic information in augmented reality. See the topic [Display scenes in augmented reality](https://developers.arcgis.com/ios/scenes-3d/display-scenes-in-augmented-reality/) in the iOS Guide for more information. +**World-scale AR** is one of three main patterns for working with geographic information in augmented reality. See the 'Edit feature attachments' sample for more specific information about the attachment editing workflow. diff --git a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard index 9babcc938..d95f232e3 100644 --- a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard +++ b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard @@ -1,9 +1,9 @@ - + - + diff --git a/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/README.md b/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/README.md index 79e113335..a66f55c31 100644 --- a/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/README.md +++ b/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/README.md @@ -40,7 +40,7 @@ The data in this sample shows the roads and trails in the Canyonlands National P ## Additional information -For more information about offline workflows, see [Offline maps, scenes, and data](https://developers.arcgis.com/ios/offline-maps-scenes-and-data/) in the *ArcGIS Developers* guide. +**Note:** preplanned areas using the Scheduled Updates workflow are read-only. For preplanned areas that can be edited on the end-user device, see the [Download preplanned map area](https://developers.arcgis.com/net/android/sample-code/download-preplanned-map-area/) sample. For more information about offline workflows, see [Offline maps, scenes, and data](https://developers.arcgis.com/documentation/mapping-apis-and-location-services/offline/) in the *ArcGIS Developers* guide. ## Tags diff --git a/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/README.md b/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/README.md index ad6b5376b..97c342e5a 100644 --- a/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/README.md @@ -60,6 +60,10 @@ Example barrier conditions for the default dataset: The [Naperville electrical](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample. +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + ## Tags category comparison, condition barriers, network analysis, network attribute comparison, subnetwork trace, trace configuration, traversability, utility network, validate consistency From 381a0e79b4e56ca54ebc599dfc9c386aaeb7a5ec Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 22 Apr 2021 14:34:16 -0700 Subject: [PATCH 059/109] Renamed display device location --- arcgis-ios-sdk-samples.xcodeproj/project.pbxproj | 6 +++--- .../Content Display Logic/ContentPList.plist | 2 +- .../DisplayLocation.storyboard | 0 .../DisplayLocationSettingsViewController.swift | 0 .../DisplayLocationViewController.swift | 0 .../README.md | 2 +- .../README.metadata.json | 2 +- .../display-device-location-1.png | Bin .../display-device-location-2.png | Bin 9 files changed, 6 insertions(+), 6 deletions(-) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/DisplayLocation.storyboard (100%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/DisplayLocationSettingsViewController.swift (100%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/DisplayLocationViewController.swift (100%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/README.md (98%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/README.metadata.json (93%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/display-device-location-1.png (100%) rename arcgis-ios-sdk-samples/Maps/{Display device location => Display device location with autopan modes}/display-device-location-2.png (100%) diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index b87f95932..75396f180 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -3166,7 +3166,7 @@ 3ED028101B8E3A8400ACA70D /* Change viewpoint */, 3ED028331B8E3A8500ACA70D /* Map rotation */, 3ED0284D1B8E3A8500ACA70D /* Show magnifier */, - 3ED028181B8E3A8400ACA70D /* Display device location */, + 3ED028181B8E3A8400ACA70D /* Display device location with autopan modes */, 3ED028521B8E3A8500ACA70D /* Take screenshot */, 3ED028011B8E3A8400ACA70D /* Create and save a map */, 3E6C77141CCFC33100E89873 /* Identify layers */, @@ -3218,14 +3218,14 @@ path = "Change viewpoint"; sourceTree = ""; }; - 3ED028181B8E3A8400ACA70D /* Display device location */ = { + 3ED028181B8E3A8400ACA70D /* Display device location with autopan modes */ = { isa = PBXGroup; children = ( 3ED0281A1B8E3A8400ACA70D /* DisplayLocation.storyboard */, 3ED0281B1B8E3A8400ACA70D /* DisplayLocationViewController.swift */, C7237D0D2190F07500A72C76 /* DisplayLocationSettingsViewController.swift */, ); - path = "Display device location"; + path = "Display device location with autopan modes"; sourceTree = ""; }; 3ED028201B8E3A8400ACA70D /* Display drawing status */ = { diff --git a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist index 6acbc58da..233189cd5 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist +++ b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist @@ -129,7 +129,7 @@ displayName - Display device location + Display device location with autopan modes storyboardName DisplayLocation descriptionText diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocation.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocation.storyboard similarity index 100% rename from arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocation.storyboard rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocation.storyboard diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocationSettingsViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocationSettingsViewController.swift similarity index 100% rename from arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocationSettingsViewController.swift rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocationSettingsViewController.swift diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocationViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocationViewController.swift similarity index 100% rename from arcgis-ios-sdk-samples/Maps/Display device location/DisplayLocationViewController.swift rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/DisplayLocationViewController.swift diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.md similarity index 98% rename from arcgis-ios-sdk-samples/Maps/Display device location/README.md rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.md index e2966f7c8..0376789ca 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.md @@ -1,4 +1,4 @@ -# Display device location +# Display device location with autopan modes Display your current position on the map, as well as switch between different types of auto-pan modes. diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/README.metadata.json b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.metadata.json similarity index 93% rename from arcgis-ios-sdk-samples/Maps/Display device location/README.metadata.json rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.metadata.json index e1a422422..99dea9adc 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location/README.metadata.json +++ b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/README.metadata.json @@ -31,5 +31,5 @@ "DisplayLocationSettingsViewController.swift", "DisplayLocationViewController.swift" ], - "title": "Display device location" + "title": "Display device location with autopan modes" } diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/display-device-location-1.png b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/display-device-location-1.png similarity index 100% rename from arcgis-ios-sdk-samples/Maps/Display device location/display-device-location-1.png rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/display-device-location-1.png diff --git a/arcgis-ios-sdk-samples/Maps/Display device location/display-device-location-2.png b/arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/display-device-location-2.png similarity index 100% rename from arcgis-ios-sdk-samples/Maps/Display device location/display-device-location-2.png rename to arcgis-ios-sdk-samples/Maps/Display device location with autopan modes/display-device-location-2.png From 01e74520de6f1d8ed749a12f88066664b884cfdf Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Thu, 22 Apr 2021 17:03:20 -0700 Subject: [PATCH 060/109] Updated to group layers --- .../DistanceMeasurementAnalysis.storyboard | 4 ++-- .../Augmented reality/Display scenes in tabletop AR/README.md | 2 +- .../Maps/Display layer view state/README.md | 2 +- arcgis-ios-sdk-samples/Search/Find address/README.md | 4 ++++ arcgis-ios-sdk-samples/Search/Find place/README.md | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard b/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard index e3daf0e02..542d9d33b 100644 --- a/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard +++ b/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard @@ -1,9 +1,9 @@ - + - + diff --git a/arcgis-ios-sdk-samples/Augmented reality/Display scenes in tabletop AR/README.md b/arcgis-ios-sdk-samples/Augmented reality/Display scenes in tabletop AR/README.md index c74a6eccd..d0464824a 100644 --- a/arcgis-ios-sdk-samples/Augmented reality/Display scenes in tabletop AR/README.md +++ b/arcgis-ios-sdk-samples/Augmented reality/Display scenes in tabletop AR/README.md @@ -42,7 +42,7 @@ This sample uses the [Philadelphia Mobile Scene Package](https://www.arcgis.com/ This sample requires a device that is compatible with ARKit 1.0 on iOS. -**Tabletop AR** is one of three main patterns for working with geographic information in augmented reality. See the topic [Display scenes in augmented reality](https://developers.arcgis.com/ios/scenes-3d/display-scenes-in-augmented-reality/) in the iOS Guide for more information. +**Tabletop AR** is one of three main patterns for working with geographic information in augmented reality. This sample uses the ArcGIS Runtime Toolkit. See the section [Enable your app for AR using AR Toolkit](https://developers.arcgis.com/ios/scenes-3d/display-scenes-in-augmented-reality/) in the iOS Guide to learn about the toolkit and how to add it to your app. diff --git a/arcgis-ios-sdk-samples/Maps/Display layer view state/README.md b/arcgis-ios-sdk-samples/Maps/Display layer view state/README.md index a9913b7f1..0b33c72de 100644 --- a/arcgis-ios-sdk-samples/Maps/Display layer view state/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display layer view state/README.md @@ -45,4 +45,4 @@ The following are members of the `AGSLayerViewState` enum: ## Tags -layer, load, map, status, view, visibility \ No newline at end of file +layer, load, map, status, view, visibility diff --git a/arcgis-ios-sdk-samples/Search/Find address/README.md b/arcgis-ios-sdk-samples/Search/Find address/README.md index 0c9aefc42..e75f2101d 100644 --- a/arcgis-ios-sdk-samples/Search/Find address/README.md +++ b/arcgis-ios-sdk-samples/Search/Find address/README.md @@ -26,6 +26,10 @@ For simplicity, the sample comes loaded with a set of suggested addresses. Choos * AGSGeocodeResult * AGSLocatorTask +## About the data + +This sample uses the [World Geocoding Service](https://www.arcgis.com/home/item.html?id=305f2e55e67f4389bef269669fc2e284). + ## Tags address, geocode, locator, search diff --git a/arcgis-ios-sdk-samples/Search/Find place/README.md b/arcgis-ios-sdk-samples/Search/Find place/README.md index 260d3d4b6..5e2b463d1 100644 --- a/arcgis-ios-sdk-samples/Search/Find place/README.md +++ b/arcgis-ios-sdk-samples/Search/Find place/README.md @@ -42,7 +42,7 @@ Choose a type of place in the first field and an area to search within in the se ## About the data -This sample uses the [world locator service](https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer). +This sample uses the [World Geocoding Service](https://www.arcgis.com/home/item.html?id=305f2e55e67f4389bef269669fc2e284). ## Tags From 3c41058451d1e26a77c9b779a3d2af210ae20913 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Fri, 23 Apr 2021 15:18:51 -0700 Subject: [PATCH 061/109] Address review feedback regarding text. --- ...iceLocationWithNMEADataSourcesViewController.swift | 11 +++++++++-- .../README.md | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift index 85838e96f..fb60ba2ba 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift @@ -191,7 +191,10 @@ extension DisplayDeviceLocationWithNMEADataSourcesViewController: AGSNMEALocatio distanceFormatter.string(from: horizontalAccuracy), distanceFormatter.string(from: verticalAccuracy) ) - statusLabel.text = accuracyText + "\n" + satelliteInfoText + statusLabel.text = """ + \(accuracyText) + \(satelliteInfoText) + """ } func nmeaLocationDataSource(_ NMEALocationDataSource: AGSNMEALocationDataSource, satellitesDidChange satellites: [AGSNMEASatelliteInfo]) { @@ -203,7 +206,11 @@ extension DisplayDeviceLocationWithNMEADataSourcesViewController: AGSNMEALocatio .map { String($0.satelliteID) } .joined(separator: ", ") satelliteInfoText = String( - format: "%d satellites in view\nSystem(s): %@\nIDs: %@", + format: """ + %d satellites in view + System(s): %@ + IDs: %@ + """, satellites.count, satelliteSystemsText, idText diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index e93a5b912..4d6df1862 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -44,7 +44,7 @@ To support GNSS device connection in an app, here are a few steps: * Enable Bluetooth connection in the device settings or connect via cable connection. * Refer to the device manufacturer's documentation to get its protocol string and add the protocol to the app’s `Info.plist` under the `UISupportedExternalAccessoryProtocols` key. -* When working with any MFi accessory, the end user must register their iOS app with the accessory manufacturer first to whitelist their app before submitting it to the AppStore for approval. This is a requirement by Apple and stated in the iOS Developer Program License Agreement. +* When working with any MFi accessory, the end user must register their iOS app with the accessory manufacturer first to whitelist their app before submitting it to the App Store for approval. This is a requirement by Apple and stated in the iOS Developer Program License Agreement. Please read Apple's documentation below for further details. From f9463a4ccc62bc04217c86f5dd6810a657247bd2 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 23 Apr 2021 16:12:36 -0700 Subject: [PATCH 062/109] Updated up to Trace utility network --- arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md | 2 +- arcgis-ios-sdk-samples/Search/Reverse geocode/README.md | 4 ++++ .../Utility network/Perform valve isolation trace/README.md | 4 ++++ .../Utility network/Trace utility network/README.md | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md index 654d6bfde..c0238567b 100644 --- a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md +++ b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md @@ -34,4 +34,4 @@ Esri now hosts an [OpenStreetMap vector layer on ArcGIS Online](https://www.arcg ## Tags -basemap style, layers, map, open, OpenStreetMap, OSM, street +basemap, layers, map, open, OpenStreetMap, OSM, street diff --git a/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md b/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md index f4010ddec..8fa7065fd 100644 --- a/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md +++ b/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md @@ -25,6 +25,10 @@ Tap the map to see the nearest address displayed in a callout. * AGSLocatorTask * AGSReverseGeocodeParameters +## About the data + +This sample uses the [World Geocoding Service](https://www.arcgis.com/home/item.html?id=305f2e55e67f4389bef269669fc2e284). + ## Tags address, geocode, locate, reverse geocode, search diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md index da763e998..2a0e573ef 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md @@ -53,6 +53,10 @@ Tap "Category" to create and set the configuration's filter barriers with a util The [Naperville gas network feature service](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleGas/FeatureServer), hosted on ArcGIS Online, contains a utility network used to run the isolation trace shown in this sample. +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + ## Tags category comparison, condition barriers, isolated features, network analysis, subnetwork trace, trace configuration, trace filter, utility network diff --git a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md index c30ac5c0b..eca25263e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md @@ -54,6 +54,10 @@ Tap on one or more features while "Start" or "Barrier" is selected. When a junct The [Naperville electrical](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample. +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + ## Tags condition barriers, downstream trace, network analysis, subnetwork trace, trace configuration, traversability, upstream trace, utility network, validate consistency From fb01a2a3699a57d2fab0714d19c8a4e5ab526881 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Fri, 23 Apr 2021 16:15:41 -0700 Subject: [PATCH 063/109] Update source to use BT picker. --- ...ionWithNMEADataSourcesViewController.swift | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift index fb60ba2ba..70e2a5192 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift @@ -64,28 +64,42 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { // MARK: Actions - @IBAction func chooseDataSource(_ sender: UIBarButtonItem) { - let alertController = UIAlertController( - title: "Choose an NMEA data source.", - message: nil, - preferredStyle: .actionSheet - ) - // Populate from connected GNSS surveyor devices. - EAAccessoryManager.shared().connectedAccessories.forEach { accessory in + /// The Bluetooth accessory picker dismissed with no error. + func accessoryPickerDidDisappear() { + for accessory in EAAccessoryManager.shared().connectedAccessories { // The protocol string to establish the EASession. guard let protocolString = accessory.protocolStrings.first(where: { supportedProtocolStrings.contains($0) }) else { // Skip any device which protocol is not included in the plist. // This typically shouldn't happen, unless the device requires // additional configuration. - return + continue } - let action = UIAlertAction(title: accessory.name, style: .default) { [self] _ in - nmeaLocationDataSource = AGSNMEALocationDataSource(eaAccessory: accessory, protocol: protocolString) - nmeaLocationDataSource?.locationChangeHandlerDelegate = self - start() + // Only read from the first supported accessory. + nmeaLocationDataSource = AGSNMEALocationDataSource(eaAccessory: accessory, protocol: protocolString) + nmeaLocationDataSource?.locationChangeHandlerDelegate = self + start() + break + } + } + + @IBAction func chooseDataSource(_ sender: UIBarButtonItem) { + let alertController = UIAlertController( + title: "Choose an NMEA data source.", + message: nil, + preferredStyle: .actionSheet + ) + // Add real data source to the options. + let realDataSourceAction = UIAlertAction(title: "Device", style: .default) { [self] _ in + // Displays an alert to pair the device with a Bluetooth accessory. + EAAccessoryManager.shared().showBluetoothAccessoryPicker(withNameFilter: nil) { error in + if let error = error { + presentAlert(error: error) + } else { + accessoryPickerDidDisappear() + } } - alertController.addAction(action) } + alertController.addAction(realDataSourceAction) // Add mock data source to the options. let mockDataSourceAction = UIAlertAction(title: "Mock Data", style: .default) { [self] _ in nmeaLocationDataSource = AGSNMEALocationDataSource(receiverSpatialReference: .wgs84()) From 04e404a0329e0414696a1a8c189654f054c4c11d Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 23 Apr 2021 16:19:28 -0700 Subject: [PATCH 064/109] Updated UN readmes --- arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md | 2 +- arcgis-ios-sdk-samples/Search/Reverse geocode/README.md | 4 ++++ .../Utility network/Perform valve isolation trace/README.md | 4 ++++ .../Utility network/Trace utility network/README.md | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md index 654d6bfde..c0238567b 100644 --- a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md +++ b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.md @@ -34,4 +34,4 @@ Esri now hosts an [OpenStreetMap vector layer on ArcGIS Online](https://www.arcg ## Tags -basemap style, layers, map, open, OpenStreetMap, OSM, street +basemap, layers, map, open, OpenStreetMap, OSM, street diff --git a/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md b/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md index f4010ddec..8fa7065fd 100644 --- a/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md +++ b/arcgis-ios-sdk-samples/Search/Reverse geocode/README.md @@ -25,6 +25,10 @@ Tap the map to see the nearest address displayed in a callout. * AGSLocatorTask * AGSReverseGeocodeParameters +## About the data + +This sample uses the [World Geocoding Service](https://www.arcgis.com/home/item.html?id=305f2e55e67f4389bef269669fc2e284). + ## Tags address, geocode, locate, reverse geocode, search diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md index da763e998..2a0e573ef 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.md @@ -53,6 +53,10 @@ Tap "Category" to create and set the configuration's filter barriers with a util The [Naperville gas network feature service](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleGas/FeatureServer), hosted on ArcGIS Online, contains a utility network used to run the isolation trace shown in this sample. +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + ## Tags category comparison, condition barriers, isolated features, network analysis, subnetwork trace, trace configuration, trace filter, utility network diff --git a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md index c30ac5c0b..eca25263e 100644 --- a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.md @@ -54,6 +54,10 @@ Tap on one or more features while "Start" or "Barrier" is selected. When a junct The [Naperville electrical](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample. +## Additional information + +Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the [Utility Network user type extension](https://enterprise.arcgis.com/en/portal/latest/administer/windows/license-user-type-extensions.htm#ESRI_SECTION1_41D78AD9691B42E0A8C227C113C0C0BF). Please refer to the [utility network services documentation](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/utility-network-services.htm). + ## Tags condition barriers, downstream trace, network analysis, subnetwork trace, trace configuration, traversability, upstream trace, utility network, validate consistency From 850bf65f90bdd653599378d517c589817f401708 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 23 Apr 2021 16:23:35 -0700 Subject: [PATCH 065/109] Reverted storyboard changes --- .../DistanceMeasurementAnalysis.storyboard | 4 ++-- .../ApplyMosaicRuleToRasters.storyboard | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard b/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard index 542d9d33b..e3daf0e02 100644 --- a/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard +++ b/arcgis-ios-sdk-samples/Analysis/Distance measurement analysis/DistanceMeasurementAnalysis.storyboard @@ -1,9 +1,9 @@ - + - + diff --git a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard index d95f232e3..9babcc938 100644 --- a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard +++ b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRasters.storyboard @@ -1,9 +1,9 @@ - + - + From 2e0a2ba59c080b3d451940c21e430a91b1577a52 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Fri, 23 Apr 2021 16:25:20 -0700 Subject: [PATCH 066/109] Fixed metadata --- .../Layers/OpenStreetMap layer/README.metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.metadata.json b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.metadata.json index 16563759c..a6d7766ca 100644 --- a/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.metadata.json +++ b/arcgis-ios-sdk-samples/Layers/OpenStreetMap layer/README.metadata.json @@ -8,7 +8,7 @@ "keywords": [ "OSM", "OpenStreetMap", - "basemap style", + "basemap", "layers", "map", "open", From 7d682919d214aa51029ec238bf344ec7d48ffd0d Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 26 Apr 2021 14:39:19 -0700 Subject: [PATCH 067/109] Apply suggestions from code review Co-authored-by: Philip Ridgeway --- .../Display content of utility network container/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md index 50e5f0592..ff7414914 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/README.md @@ -21,12 +21,12 @@ Tap on a container feature to show all features inside the container. The conta 5. Identify the tapped feature and create an `AGSUtilityElement` from it. 6. Get the associations for this element using `AGSUtilityNetwork.associations(with:completion:)`. 7. Turn-off the visibility of all of the map's `operationalLayers`. -8. Get the features for the `AGSUtilityElement`(s) from the associations using `AGSUtilityNetwork.features(for:completion:)` +8. Get the features for the `AGSUtilityElement`(s) from the associations using `AGSUtilityNetwork.features(for:completion:)`. 9. Add an `AGSGraphic` with the same geometry and symbol as these features. 10. Add another `AGSGraphic` that represents this extent and zoom to this extent with some buffer. -11. Get associations for this extent using `AGSUtilityNetwork.associations(withExtent:completion:)` +11. Get associations for this extent using `AGSUtilityNetwork.associations(withExtent:completion:)`. 12. Add an `AGSGraphic` to represent the association geometry between them using a symbol that distinguishes between `attachment` and `connectivity` association type. -13. Turn-on the visibility of all `operationalLayers`, clear the `AGSGraphics` and zoom out to previous extent to exit container view. +13. Turn-on the visibility of all `operationalLayers`, clear the `AGSGraphic` objects, and zoom out to previous extent to exit container view. ## Relevant API From 18f61ecd9d15f2e9176cdd105a27f2d2d742e6b9 Mon Sep 17 00:00:00 2001 From: Vivian Quach Date: Mon, 26 Apr 2021 15:18:22 -0700 Subject: [PATCH 068/109] Removed makeMap --- ...ntentUtilityNetworkContainerViewController.swift | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift index 28c9350f9..faf447979 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display content of utility network container/DisplayContentUtilityNetworkContainerViewController.swift @@ -19,7 +19,9 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS /// The map view managed by the view controller. @IBOutlet var mapView: AGSMapView! { didSet { - makeMap() + mapView.map = AGSMap( + url: URL(string: "https://sampleserver7.arcgisonline.com/portal/home/item.html?id=813eda749a9444e4a9d833a4db19e1c8")! + ) mapView.setViewpoint(AGSViewpoint(latitude: 41.801504, longitude: -88.163718, scale: 4e3)) } } @@ -73,15 +75,6 @@ class DisplayContentUtilityNetworkContainerViewController: UIViewController, AGS } } - /// Create a map. - /// - /// - Returns: An `AGSMap` object. - func makeMap() { - let webMapURL = URL(string: "https://sampleserver7.arcgisonline.com/portal/home/item.html?id=813eda749a9444e4a9d833a4db19e1c8")! - let map = AGSMap(url: webMapURL) - mapView.map = map - } - /// Create and load the utility network using the feature service URL. func loadUtilityNetwork() { guard let map = mapView.map else { return } From f118ac8f7cae8b8d735075d65f6735946a039f21 Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 27 Apr 2021 15:22:45 -0700 Subject: [PATCH 069/109] Address issues in storyboard. --- ...eviceLocationWithNMEADataSources.storyboard | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard index d4be8a583..dd46cf6ae 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard @@ -1,9 +1,9 @@ - + - + @@ -24,20 +24,29 @@ - + + + @@ -79,11 +88,12 @@ + + - From c1e3d2838e9804953f78ad198a65c243fe487c6c Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 27 Apr 2021 15:23:16 -0700 Subject: [PATCH 070/109] Update source code. --- ...ionWithNMEADataSourcesViewController.swift | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift index 70e2a5192..d2abcfa6d 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSourcesViewController.swift @@ -24,8 +24,10 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { mapView.map = AGSMap(basemapStyle: .arcGISNavigation) } } + /// The label to display accuracy info. + @IBOutlet var accuracyStatusLabel: UILabel! /// The label to display satellites info. - @IBOutlet var statusLabel: UILabel! + @IBOutlet var satelliteStatusLabel: UILabel! /// The button to choose a data source and start the demo. @IBOutlet var sourceBarButtonItem: UIBarButtonItem! /// The button to reset pan mode to "recenter". @@ -37,19 +39,15 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { /// The protocols specified in the `Info.plist` that the app uses to /// communicate with external accessory hardware. - let supportedProtocolStrings: [String] = { - guard let protocols = Bundle.main.object(forInfoDictionaryKey: "UISupportedExternalAccessoryProtocols") as? [String] else { - return [] - } - return protocols - }() + let supportedProtocolStrings: Set = Bundle.main + .object(forInfoDictionaryKey: "UISupportedExternalAccessoryProtocols") + .flatMap { $0 as? [String] } + .map(Set.init) ?? [] // MARK: Instance properties /// An NMEA location data source, to parse NMEA data. var nmeaLocationDataSource: AGSNMEALocationDataSource? - /// A string to hold the latest satellite info. - var satelliteInfoText = "Satellites info will be shown here." /// A mock data source to read NMEA sentences from a local file, and generate /// mock NMEA data every fixed amount of time. let mockNMEADataSource = SimulatedNMEADataSource(nmeaSourceFile: Bundle.main.url(forResource: "Redlands", withExtension: "nmea")!, speed: 1.5) @@ -147,8 +145,8 @@ class DisplayDeviceLocationWithNMEADataSourcesViewController: UIViewController { resetBarButtonItem.isEnabled = false sourceBarButtonItem.isEnabled = true // Reset the status text. - statusLabel.text = "Location info will be shown here." - satelliteInfoText = "Satellites info will be shown here." + accuracyStatusLabel.text = "Accuracy info will be shown here." + satelliteStatusLabel.text = "Satellites info will be shown here." // Reset and stop the location display. mapView.locationDisplay.autoPanModeChangedHandler = nil mapView.locationDisplay.autoPanMode = .off @@ -205,10 +203,7 @@ extension DisplayDeviceLocationWithNMEADataSourcesViewController: AGSNMEALocatio distanceFormatter.string(from: horizontalAccuracy), distanceFormatter.string(from: verticalAccuracy) ) - statusLabel.text = """ - \(accuracyText) - \(satelliteInfoText) - """ + accuracyStatusLabel.text = accuracyText } func nmeaLocationDataSource(_ NMEALocationDataSource: AGSNMEALocationDataSource, satellitesDidChange satellites: [AGSNMEASatelliteInfo]) { @@ -219,7 +214,7 @@ extension DisplayDeviceLocationWithNMEADataSourcesViewController: AGSNMEALocatio let idText = satellites .map { String($0.satelliteID) } .joined(separator: ", ") - satelliteInfoText = String( + satelliteStatusLabel.text = String( format: """ %d satellites in view System(s): %@ From 63c4bc3c3b0c9d69cc9a5148f2a5c54a24a167ec Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 27 Apr 2021 15:29:46 -0700 Subject: [PATCH 071/109] Update README. --- .../Display device location with NMEA data sources/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md index 4d6df1862..462f62ebf 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/README.md @@ -6,7 +6,7 @@ Parse NMEA sentences and use the results to show device location on the map. ## Use case -NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. Devices without a built-in GNSS receiver can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected through Bluetooth or a serial port. +NMEA sentences can be retrieved from GNSS/GPS receivers and parsed into a series of coordinates with additional information. iOS devices can retrieve NMEA sentences by using a separate GNSS dongle, commonly connected through Bluetooth or cable. The NMEA location data source allows for detailed interrogation of the information coming from the GNSS receiver. For example, allowing you to report the number of satellites in view, accuracy of the location, etc. From 2fe3ea341fac2f208b8f238678972cd969f020ab Mon Sep 17 00:00:00 2001 From: Ting Chen Date: Tue, 27 Apr 2021 15:55:56 -0700 Subject: [PATCH 072/109] Update storyboard. --- .../DisplayDeviceLocationWithNMEADataSources.storyboard | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard index dd46cf6ae..ab7cb41db 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/DisplayDeviceLocationWithNMEADataSources.storyboard @@ -22,7 +22,7 @@ - +