diff --git a/.gitignore b/.gitignore index dfdbee132..cf3602ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,9 @@ xcuserdata/ ## Portal Item Data /Portal\ Data + +## Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +Packages/ +Package.pins +Package.resolved diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 35a6347db..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "arcgis-runtime-toolkit-ios"] - path = arcgis-runtime-toolkit-ios - url = https://github.com/Esri/arcgis-runtime-toolkit-ios diff --git a/.swiftlint.yml b/.swiftlint.yml index 1f5e475a5..c6cfc6643 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -82,4 +82,3 @@ trailing_whitespace: excluded: - Pods -- arcgis-runtime-toolkit-ios diff --git a/README.md b/README.md index 93a2a8370..81f764955 100644 --- a/README.md +++ b/README.md @@ -25,41 +25,34 @@ The ```main``` branch of this repository contains samples configured for the lat ## Requirements -* [ArcGIS Runtime SDK for iOS](https://developers.arcgis.com/ios/) 100.10.0 (or newer) -* [ArcGIS Runtime Toolkit for iOS](https://github.com/Esri/arcgis-runtime-toolkit-ios) 100.10.0 (or newer) +* [ArcGIS Runtime SDK for iOS](https://developers.arcgis.com/ios/) 100.11.0 (or newer) +* [ArcGIS Runtime Toolkit for iOS](https://github.com/Esri/arcgis-runtime-toolkit-ios) 100.11.0 (or newer) * Xcode 12.0 (or newer) -The *ArcGIS Runtime SDK Samples app* has a *Target SDK* version of *12.0*, meaning that it can run on devices with *iOS 12.0* or newer. +The *ArcGIS Runtime SDK Samples app* has a *Target SDK* version of *13.0*, meaning that it can run on devices with *iOS 13.0* or newer. -## Building samples using installed SDK +## Building Samples Using Swift Package Manager 1. **Fork** and then **clone** the repository - > Make sure to use the "recursive" option to ensure you get the **ArcGIS Runtime Toolkit** submodule - > - >`git clone --recursive [URL to Git repo]` - > - > If you've already cloned the repo without the submodule, you can load the submodule using - > - >`git submodule update --init` -1. **Install** the ArcGIS Runtime SDK for iOS to a central location on your Mac as described [here](https://developers.arcgis.com/ios/get-started) 1. **Open** the `arcgis-ios-sdk-samples.xcodeproj` **project** file + > The project has been configured to use the `arcgis-runtime-toolkit-ios` package, which provides the `ArcGISToolkit` framework as well as the `ArcGIS` framework. 1. **Run** the `arcgis-ios-sdk-samples` app target - > If you get the error message saying _"This Copy Files build phase contains a reference to a missing file 'ArcGISToolkit.framework'"_, you probably didn't clone the repo to include it's submodule. See Step 1 above. -## Building samples with CocoaPods +> To add the Swift packages to your own projects, consult the documentation for the [ArcGIS Runtime iOS Toolkit](https://github.com/Esri/arcgis-runtime-toolkit-ios/#swift-package-manager) and [ArcGIS Runtime iOS SDK](https://github.com/Esri/arcgis-runtime-ios#instructions). + +## Building Samples Using CocoaPods 1. **Fork** and then **clone** the repository 1. **Install** the ArcGIS Runtime SDK for iOS by running the `pod install` command in the folder where you cloned this repository 1. **Open** the `arcgis-ios-sdk-samples.xcworkspace` **workspace** file -1. **Select** the `arcgis-ios-sdk-samples` project node, go to the `Build Phases` tab, and **delete** the phases for `Embed Frameworks`. (This phase conflicts with CocoaPods and is only required when using the installed SDK as described in the previous section) -1. **Select** the `ArcGISToolkit.xcodeproj` project node and **delete** it. (this project dependency conflicts with CocoaPods and is only required when using the installed SDK as described in the previous section) +1. **Select** the `arcgis-ios-sdk-samples` project node, go to the `Swift Packages` tab, and **delete** the `arcgis-runtime-toolkit-ios` package. This Swift package conflicts with CocoaPods and is only required when using the Swift Package Manager as described in the previous section. 1. **Run** the `arcgis-ios-sdk-samples` app target ## Sample Data Some sample data is too large to store in the repository, so it is automatically downloaded at build time. The first time the app is built, a build script downloads the necessary data to `Portal Data`. The script only downloads data files that do not already exist, so subsequent builds will take significantly less time. -## Configure app secrets +## Configure App Secrets As a best-practices principle, the project conceals app secrets from source code by generating and compiling an `AppSecrets.swift` source code file at build time using a custom build rule. diff --git a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj index f0b8734ef..b87f95932 100644 --- a/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj +++ b/arcgis-ios-sdk-samples.xcodeproj/project.pbxproj @@ -46,8 +46,11 @@ 00686FD62481CF4D00EDA705 /* NavigateARNavigatorViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00686FCF2480889900EDA705 /* NavigateARNavigatorViewController.swift */; }; 0069F4BE25F0111D00CA7BD2 /* CreateLoadReport.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0069F4BD25F0111D00CA7BD2 /* CreateLoadReport.storyboard */; }; 0069F4C225F0118200CA7BD2 /* CreateLoadReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0069F4C125F0118200CA7BD2 /* CreateLoadReportViewController.swift */; }; + 006A786A262F9F15001D2A5E /* ArcGISToolkit in Frameworks */ = {isa = PBXBuildFile; productRef = 006A7869262F9F15001D2A5E /* ArcGISToolkit */; }; 007FC9482534E8AE00D8D9A1 /* darkmode.css in Resources */ = {isa = PBXBuildFile; fileRef = 007FC9452534E8AE00D8D9A1 /* darkmode.css */; }; 007FC9492534E8AE00D8D9A1 /* solarized-dark.css in Resources */ = {isa = PBXBuildFile; fileRef = 007FC9472534E8AE00D8D9A1 /* solarized-dark.css */; }; + 0083AA192628ED18003A28C8 /* ProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0083AA162628ED18003A28C8 /* ProgressViewController.xib */; }; + 0083AA1A2628ED18003A28C8 /* ProgressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0083AA172628ED18003A28C8 /* ProgressViewController.swift */; }; 008D175224EEEEBD0001BB8F /* loudoun_anno.geodatabase in Resources */ = {isa = PBXBuildFile; fileRef = 008D175124EEEEBD0001BB8F /* loudoun_anno.geodatabase */; settings = {ASSET_TAGS = (loudoun_anno, ); }; }; 008D175724EEF3FE0001BB8F /* EditWithBranchVersioningViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008D175624EEF3FE0001BB8F /* EditWithBranchVersioningViewController.swift */; }; 008D175924EEF4390001BB8F /* EditWithBranchVersioning.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 008D175824EEF4390001BB8F /* EditWithBranchVersioning.storyboard */; }; @@ -225,9 +228,6 @@ 3E41DD7A1B9F836600DA11CC /* AddFeaturesViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3E41DD711B9A1F4600DA11CC /* AddFeaturesViewController.swift */; }; 3E41DD7B1B9F836600DA11CC /* DeleteFeaturesViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3E41DD761B9F5C6C00DA11CC /* DeleteFeaturesViewController.swift */; }; 3E4A64B01D8B37DA00CF930C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3E4A64AF1D8B37DA00CF930C /* Settings.bundle */; }; - 3E4B05F71B39EF250072E514 /* SVIndefiniteAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E4B05E91B39EF250072E514 /* SVIndefiniteAnimatedView.m */; }; - 3E4B05F81B39EF250072E514 /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3E4B05EB1B39EF250072E514 /* SVProgressHUD.bundle */; }; - 3E4B05F91B39EF250072E514 /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E4B05ED1B39EF250072E514 /* SVProgressHUD.m */; }; 3E4BF4421C5AE98300D85919 /* FindAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E4BF4411C5AE98300D85919 /* FindAddressViewController.swift */; }; 3E4BF4441C5AEA6500D85919 /* WorldAddressesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E4BF4431C5AEA6500D85919 /* WorldAddressesViewController.swift */; }; 3E4BF4461C5AED5100D85919 /* FindAddress.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3E4BF4451C5AED5100D85919 /* FindAddress.storyboard */; }; @@ -612,9 +612,6 @@ 4C6FAE1A22F8A37D00BE2D0B /* ControlAnnotationSublayerVisibilityViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CE15D4B22F37A2D005F2968 /* ControlAnnotationSublayerVisibilityViewController.swift */; }; 4C6FAE1B22F8A38300BE2D0B /* ControlAnnotationSublayerVisibilitySublayersViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CE15D5222F380FB005F2968 /* ControlAnnotationSublayerVisibilitySublayersViewController.swift */; }; 4C6FAE1C22F8A38700BE2D0B /* ControlAnnotationSublayerVisibilitySublayerCell.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C54BF2C22F4C0940096D23C /* ControlAnnotationSublayerVisibilitySublayerCell.swift */; }; - 4C72117020BF444C004A7DD9 /* SVProgressAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C72116E20BF444C004A7DD9 /* SVProgressAnimatedView.m */; }; - 4C72117320BF4457004A7DD9 /* SVRadialGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C72117220BF4457004A7DD9 /* SVRadialGradientLayer.m */; }; - 4C73C837211130E000B0F9C7 /* ArcGIS.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4C73C83421112B4300B0F9C7 /* ArcGIS.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4C783F3C2252D61200609B9C /* OpenMobileScene.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4C783F3B2252D61200609B9C /* OpenMobileScene.storyboard */; }; 4C783F3E2252D65A00609B9C /* OpenMobileSceneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C783F3D2252D65A00609B9C /* OpenMobileSceneViewController.swift */; }; 4C783F3F2252D80B00609B9C /* OpenMobileSceneViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C783F3D2252D65A00609B9C /* OpenMobileSceneViewController.swift */; }; @@ -652,7 +649,6 @@ 4CCA30D4223AEF2C009D2AEF /* IntegratedWindowsAuthenticationSearchTableViewCell.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C1EF29C220FEBAB00F73EAE /* IntegratedWindowsAuthenticationSearchTableViewCell.swift */; }; 4CCA30D5223AEF2C009D2AEF /* IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCA30BF223813BF009D2AEF /* IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift */; }; 4CCA30D6223AEF2C009D2AEF /* IntegratedWindowsAuthenticationMapViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C1EF2D0221232C500F73EAE /* IntegratedWindowsAuthenticationMapViewController.swift */; }; - 4CCC0877234E78BB00AD5F9A /* ArcGISToolkit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 97466015234265F6008EF35A /* ArcGISToolkit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4CCE7BD620D2BD34001238F5 /* DistanceMeasurementAnalysisViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CCE7BD520D2BD34001238F5 /* DistanceMeasurementAnalysisViewController.swift */; }; 4CCE7BD820D2BD4E001238F5 /* DistanceMeasurementAnalysis.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4CCE7BD720D2BD4E001238F5 /* DistanceMeasurementAnalysis.storyboard */; }; 4CD2B55F2142EB2600767D87 /* SampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD2B55E2142EB2600767D87 /* SampleTests.swift */; }; @@ -676,7 +672,6 @@ 940A73F420E588C200A06C80 /* CutGeometry.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 940A73F320E588C200A06C80 /* CutGeometry.storyboard */; }; 940A73F620E589AB00A06C80 /* CutGeometryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940A73F520E589AB00A06C80 /* CutGeometryViewController.swift */; }; 940A73F720E6BF3F00A06C80 /* CutGeometryViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 940A73F520E589AB00A06C80 /* CutGeometryViewController.swift */; }; - 9746601B234266A3008EF35A /* ArcGISToolkit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97466015234265F6008EF35A /* ArcGISToolkit.framework */; }; 97DD84671B2B869300184B41 /* xcode.css in Resources */ = {isa = PBXBuildFile; fileRef = 97DD84661B2B869300184B41 /* xcode.css */; }; 9D57A46722FDDE4400C750F4 /* LocationHistoryViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9DE9FE3222FDB7CA00142DE1 /* LocationHistoryViewController.swift */; }; 9D5EDFE3230741670019C46A /* PreplannedMapAreaTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5EDFE2230741670019C46A /* PreplannedMapAreaTableViewCell.swift */; }; @@ -828,6 +823,9 @@ F1124F0A24CFA95F00E672EC /* EditFeaturesWithFeatureLinkedAnnotation.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1124F0924CFA95F00E672EC /* EditFeaturesWithFeatureLinkedAnnotation.storyboard */; }; F1124F0C24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1124F0B24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift */; }; F1151CB5230B1B2000E55682 /* ElevationViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F1D7508E230730360018B812 /* ElevationViewController.swift */; }; + F11CED6D256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11CED6C256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift */; }; + F11CED73256C857B002A3F56 /* ShowLabelsOnLayer3D.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F11CED72256C857B002A3F56 /* ShowLabelsOnLayer3D.storyboard */; }; + F11CED76256C8BD3002A3F56 /* ShowLabelsOnLayer3DViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = F11CED6C256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift */; }; F127B8E822E0E73200E8EC29 /* MontereyElevation.tpkx in Resources */ = {isa = PBXBuildFile; fileRef = F1034FAB22D3F6C700B021DA /* MontereyElevation.tpkx */; settings = {ASSET_TAGS = (MontereyElevation, ); }; }; F12C739F250ADDB000C1E3FE /* ConfigureSubnetworkTraceViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 003BC31124E5E53200F65746 /* ConfigureSubnetworkTraceViewController.swift */; }; F12C73A0250ADDB000C1E3FE /* ConfigureSubnetworkTraceOptionsViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 003BC30E24E5E44E00F65746 /* ConfigureSubnetworkTraceOptionsViewController.swift */; }; @@ -907,13 +905,6 @@ /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ - 4C8C80BB23AC3FF5000333B3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = E4685B03237CA3C400F168CF; - remoteInfo = ArcGISToolkitTests; - }; 4CD2B5592142EAF900767D87 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 3E23A9D81AFC28F6002E2214 /* Project object */; @@ -921,20 +912,6 @@ remoteGlobalIDString = 3E23A9DF1AFC28F6002E2214; remoteInfo = "arcgis-ios-sdk-samples"; }; - 97466014234265F6008EF35A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 881233701DF601A700B2EA8E; - remoteInfo = ArcGISToolkit; - }; - 9746601D234266A3008EF35A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 8812336F1DF601A700B2EA8E; - remoteInfo = ArcGISToolkit; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -944,6 +921,7 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( + F11CED76256C8BD3002A3F56 /* ShowLabelsOnLayer3DViewController.swift in CopyFiles */, 00F359C725F2F27500A7C880 /* CreateLoadReportViewController.swift in CopyFiles */, 009B600325E5DB4700BB9A77 /* CreateSymbolStylesFromWebStylesViewController.swift in CopyFiles */, 0023F98825E717EA006B574E /* SimulatedNMEADataSource.swift in CopyFiles */, @@ -1221,18 +1199,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 4C73C838211130E000B0F9C7 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 4CCC0877234E78BB00AD5F9A /* ArcGISToolkit.framework in Embed Frameworks */, - 4C73C837211130E000B0F9C7 /* ArcGIS.xcframework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -1264,6 +1230,8 @@ 007A4250256C7A400025F582 /* AppSecrets.swift.masque */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = AppSecrets.swift.masque; path = "arcgis-ios-sdk-samples/AppSecrets.swift.masque"; sourceTree = ""; }; 007FC9452534E8AE00D8D9A1 /* darkmode.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = darkmode.css; sourceTree = ""; }; 007FC9472534E8AE00D8D9A1 /* solarized-dark.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "solarized-dark.css"; sourceTree = ""; }; + 0083AA162628ED18003A28C8 /* ProgressViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProgressViewController.xib; sourceTree = ""; }; + 0083AA172628ED18003A28C8 /* ProgressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressViewController.swift; sourceTree = ""; }; 008D175124EEEEBD0001BB8F /* loudoun_anno.geodatabase */ = {isa = PBXFileReference; lastKnownFileType = file; path = loudoun_anno.geodatabase; sourceTree = ""; }; 008D175624EEF3FE0001BB8F /* EditWithBranchVersioningViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditWithBranchVersioningViewController.swift; sourceTree = ""; }; 008D175824EEF4390001BB8F /* EditWithBranchVersioning.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = EditWithBranchVersioning.storyboard; sourceTree = ""; }; @@ -1386,12 +1354,6 @@ 3E41DD761B9F5C6C00DA11CC /* DeleteFeaturesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteFeaturesViewController.swift; sourceTree = ""; }; 3E41DD781B9F609500DA11CC /* DeleteFeatures.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DeleteFeatures.storyboard; sourceTree = ""; }; 3E4A64AF1D8B37DA00CF930C /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; - 3E4B05E81B39EF250072E514 /* SVIndefiniteAnimatedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVIndefiniteAnimatedView.h; sourceTree = ""; }; - 3E4B05E91B39EF250072E514 /* SVIndefiniteAnimatedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVIndefiniteAnimatedView.m; sourceTree = ""; }; - 3E4B05EA1B39EF250072E514 /* SVProgressHUD-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-Prefix.pch"; sourceTree = ""; }; - 3E4B05EB1B39EF250072E514 /* SVProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = SVProgressHUD.bundle; sourceTree = ""; }; - 3E4B05EC1B39EF250072E514 /* SVProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressHUD.h; sourceTree = ""; }; - 3E4B05ED1B39EF250072E514 /* SVProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressHUD.m; sourceTree = ""; }; 3E4BF4411C5AE98300D85919 /* FindAddressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FindAddressViewController.swift; sourceTree = ""; }; 3E4BF4431C5AEA6500D85919 /* WorldAddressesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WorldAddressesViewController.swift; sourceTree = ""; }; 3E4BF4451C5AED5100D85919 /* FindAddress.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = FindAddress.storyboard; sourceTree = ""; }; @@ -1458,7 +1420,6 @@ 3E8D54FA1D53E3F000E628D9 /* ScenePropertiesExpressionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScenePropertiesExpressionsViewController.swift; sourceTree = ""; }; 3EA15C731ED89EAE00B1F816 /* ChangeSublayerRenderer.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ChangeSublayerRenderer.storyboard; sourceTree = ""; }; 3EA15C741ED89EAE00B1F816 /* ChangeSublayerRendererViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeSublayerRendererViewController.swift; sourceTree = ""; }; - 3EA34D591B38C3B3003DC0E8 /* Samples-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Samples-Bridging-Header.h"; path = "Content Display Logic/Samples-Bridging-Header.h"; sourceTree = ""; }; 3EABC7891DB1772000C161C6 /* RGBRenderer.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = RGBRenderer.storyboard; sourceTree = ""; }; 3EABC78C1DB1772000C161C6 /* RGBRendererSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RGBRendererSettingsViewController.swift; sourceTree = ""; }; 3EABC78E1DB1772000C161C6 /* RGBRendererViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RGBRendererViewController.swift; sourceTree = ""; }; @@ -1662,11 +1623,6 @@ 4C66AAF62107C4F400EE6346 /* QueryMapImageSublayer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = QueryMapImageSublayer.storyboard; sourceTree = ""; }; 4C66AAF82107C50B00EE6346 /* QueryMapImageSublayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryMapImageSublayerViewController.swift; sourceTree = ""; }; 4C68A28A22DE9D3E0009F43C /* FileTypes.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = FileTypes.plist; sourceTree = ""; }; - 4C72116E20BF444C004A7DD9 /* SVProgressAnimatedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressAnimatedView.m; sourceTree = ""; }; - 4C72116F20BF444C004A7DD9 /* SVProgressAnimatedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressAnimatedView.h; sourceTree = ""; }; - 4C72117120BF4456004A7DD9 /* SVRadialGradientLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVRadialGradientLayer.h; sourceTree = ""; }; - 4C72117220BF4457004A7DD9 /* SVRadialGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVRadialGradientLayer.m; sourceTree = ""; }; - 4C73C83421112B4300B0F9C7 /* ArcGIS.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ArcGIS.xcframework; path = $HOME/Library/SDKs/ArcGIS/Frameworks/ArcGIS.xcframework; sourceTree = ""; }; 4C783F3B2252D61200609B9C /* OpenMobileScene.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = OpenMobileScene.storyboard; sourceTree = ""; }; 4C783F3D2252D65A00609B9C /* OpenMobileSceneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMobileSceneViewController.swift; sourceTree = ""; }; 4C783F412252DBAC00609B9C /* philadelphia.mspk */ = {isa = PBXFileReference; lastKnownFileType = file; path = philadelphia.mspk; sourceTree = ""; }; @@ -1706,7 +1662,6 @@ 4CF6DF1E22F2094F00A3092A /* LothianRiversAnno.mmpk */ = {isa = PBXFileReference; lastKnownFileType = file; path = LothianRiversAnno.mmpk; sourceTree = ""; }; 940A73F320E588C200A06C80 /* CutGeometry.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = CutGeometry.storyboard; sourceTree = ""; }; 940A73F520E589AB00A06C80 /* CutGeometryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CutGeometryViewController.swift; sourceTree = ""; }; - 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ArcGISToolkit.xcodeproj; path = "arcgis-runtime-toolkit-ios/Toolkit/ArcGISToolkit.xcodeproj"; sourceTree = ""; }; 97DD84661B2B869300184B41 /* xcode.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = xcode.css; sourceTree = ""; }; 9D5EDFE2230741670019C46A /* PreplannedMapAreaTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreplannedMapAreaTableViewCell.swift; sourceTree = ""; }; 9DA3CD8B23060687007CB1F3 /* MapSelectionTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSelectionTableViewController.swift; sourceTree = ""; }; @@ -1814,6 +1769,8 @@ F1034FAB22D3F6C700B021DA /* MontereyElevation.tpkx */ = {isa = PBXFileReference; lastKnownFileType = file; path = MontereyElevation.tpkx; sourceTree = ""; }; F1124F0924CFA95F00E672EC /* EditFeaturesWithFeatureLinkedAnnotation.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = EditFeaturesWithFeatureLinkedAnnotation.storyboard; sourceTree = ""; }; F1124F0B24CFA97000E672EC /* EditFeaturesWithFeatureLinkedAnnotationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditFeaturesWithFeatureLinkedAnnotationViewController.swift; sourceTree = ""; }; + F11CED6C256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowLabelsOnLayer3DViewController.swift; sourceTree = ""; }; + F11CED72256C857B002A3F56 /* ShowLabelsOnLayer3D.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ShowLabelsOnLayer3D.storyboard; sourceTree = ""; }; F140E1EA23F35E92008AC44E /* DisplayAnnotationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayAnnotationViewController.swift; sourceTree = ""; }; F140E1EC23F35EA6008AC44E /* DisplayAnnotation.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = DisplayAnnotation.storyboard; sourceTree = ""; }; F14A8F002474AD9D00242D96 /* ConfigureSubnetworkTrace.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ConfigureSubnetworkTrace.storyboard; sourceTree = ""; }; @@ -1858,7 +1815,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9746601B234266A3008EF35A /* ArcGISToolkit.framework in Frameworks */, + 006A786A262F9F15001D2A5E /* ArcGISToolkit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1947,6 +1904,15 @@ path = "Create load report"; sourceTree = ""; }; + 0083AA152628ED18003A28C8 /* Progress View Controller */ = { + isa = PBXGroup; + children = ( + 0083AA162628ED18003A28C8 /* ProgressViewController.xib */, + 0083AA172628ED18003A28C8 /* ProgressViewController.swift */, + ); + path = "Progress View Controller"; + sourceTree = ""; + }; 008D175024EEEEBD0001BB8F /* Geodatabases */ = { isa = PBXGroup; children = ( @@ -2374,9 +2340,7 @@ 4CD2B5552142EAF900767D87 /* arcgis-ios-sdk-samplesTests */, 4CB506D3224C2DBC006A3471 /* Portal Data */, 4CB506D2224C2DA5006A3471 /* Scripts */, - 4C73C83321112AFF00B0F9C7 /* Frameworks */, 3E23A9E11AFC28F6002E2214 /* Products */, - 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */, ); sourceTree = ""; }; @@ -2408,7 +2372,6 @@ 3E4B05E51B39EE920072E514 /* Shared resources */, C7E86C8E21751CFE001C65C3 /* Extensions */, 3E23AA071AFC2DE0002E2214 /* Content Display Logic */, - 3EA34D591B38C3B3003DC0E8 /* Samples-Bridging-Header.h */, 3E23A9E41AFC28F6002E2214 /* Info.plist */, ); path = "arcgis-ios-sdk-samples"; @@ -2445,6 +2408,7 @@ 3E3B2C1E1BBCA37F00A99C5E /* ContentCollectionViewController.swift */, C7760331217FAC9B0092D978 /* OptionsTableViewController.swift */, C71288192183CA81007502A6 /* Color Picker */, + 0083AA152628ED18003A28C8 /* Progress View Controller */, ); path = Controllers; sourceTree = ""; @@ -2519,29 +2483,11 @@ 3E4B05E61B39EF250072E514 /* Libraries */ = { isa = PBXGroup; children = ( - 3E4B05E71B39EF250072E514 /* SVProgressHUD */, 3EC398BD1D8B45AD0084612D /* DemoTouchManager */, ); path = Libraries; sourceTree = ""; }; - 3E4B05E71B39EF250072E514 /* SVProgressHUD */ = { - isa = PBXGroup; - children = ( - 3E4B05E81B39EF250072E514 /* SVIndefiniteAnimatedView.h */, - 3E4B05E91B39EF250072E514 /* SVIndefiniteAnimatedView.m */, - 4C72116F20BF444C004A7DD9 /* SVProgressAnimatedView.h */, - 4C72116E20BF444C004A7DD9 /* SVProgressAnimatedView.m */, - 3E4B05EA1B39EF250072E514 /* SVProgressHUD-Prefix.pch */, - 3E4B05EB1B39EF250072E514 /* SVProgressHUD.bundle */, - 3E4B05EC1B39EF250072E514 /* SVProgressHUD.h */, - 3E4B05ED1B39EF250072E514 /* SVProgressHUD.m */, - 4C72117120BF4456004A7DD9 /* SVRadialGradientLayer.h */, - 4C72117220BF4457004A7DD9 /* SVRadialGradientLayer.m */, - ); - path = SVProgressHUD; - sourceTree = ""; - }; 3E4BF43C1C5AC66700D85919 /* Search */ = { isa = PBXGroup; children = ( @@ -3573,6 +3519,7 @@ 3EEA06001D21C3E800E03774 /* Scenes */ = { isa = PBXGroup; children = ( + F11CED6A256C82A8002A3F56 /* Show labels on layer in 3D */, 00166C8524D20E0E00DD317E /* Realistic lighting and shadows */, 00ADC3B72464D45B00A3B88D /* Animate images with image overlay */, F1C81C4322FCEBD100229CAA /* Get elevation at a point */, @@ -3871,14 +3818,6 @@ path = "Query a map image sublayer"; sourceTree = ""; }; - 4C73C83321112AFF00B0F9C7 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 4C73C83421112B4300B0F9C7 /* ArcGIS.xcframework */, - ); - name = Frameworks; - sourceTree = ""; - }; 4C783F3A2252D55900609B9C /* Open mobile scene (scene package) */ = { isa = PBXGroup; children = ( @@ -4058,15 +3997,6 @@ path = "Cut geometry"; sourceTree = ""; }; - 97466011234265F6008EF35A /* Products */ = { - isa = PBXGroup; - children = ( - 97466015234265F6008EF35A /* ArcGISToolkit.framework */, - 4C8C80BC23AC3FF5000333B3 /* ArcGISToolkitTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; 9D4BA6C822FCAFAD0086D5D3 /* Show location history */ = { isa = PBXGroup; children = ( @@ -4482,6 +4412,15 @@ path = "Edit features with feature-linked annotation"; sourceTree = ""; }; + F11CED6A256C82A8002A3F56 /* Show labels on layer in 3D */ = { + isa = PBXGroup; + children = ( + F11CED6C256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift */, + F11CED72256C857B002A3F56 /* ShowLabelsOnLayer3D.storyboard */, + ); + path = "Show labels on layer in 3D"; + sourceTree = ""; + }; F140E1E823F35E61008AC44E /* Display annotation */ = { isa = PBXGroup; children = ( @@ -4660,16 +4599,17 @@ 3E23A9DE1AFC28F6002E2214 /* Resources */, 3E03F0951B056DC40078EB36 /* CopyFiles */, 3ED029A21B8E5D4D00ACA70D /* ShellScript */, - 4C73C838211130E000B0F9C7 /* Embed Frameworks */, 4CBDB3192190E88F006E5D39 /* Lint Code */, ); buildRules = ( 007A424F256C747E0025F582 /* PBXBuildRule */, ); dependencies = ( - 9746601E234266A3008EF35A /* PBXTargetDependency */, ); name = "ArcGIS Runtime SDK Samples"; + packageProductDependencies = ( + 006A7869262F9F15001D2A5E /* ArcGISToolkit */, + ); productName = "arcgis-ios-sdk-samples"; productReference = 3E23A9E01AFC28F6002E2214 /* ArcGIS Runtime SDK Samples.app */; productType = "com.apple.product-type.application"; @@ -4766,14 +4706,11 @@ Base, ); mainGroup = 3E23A9D71AFC28F6002E2214; + packageReferences = ( + 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */, + ); productRefGroup = 3E23A9E11AFC28F6002E2214 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 97466011234265F6008EF35A /* Products */; - ProjectRef = 97466010234265F6008EF35A /* ArcGISToolkit.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 3E23A9DF1AFC28F6002E2214 /* ArcGIS Runtime SDK Samples */, @@ -4782,23 +4719,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 4C8C80BC23AC3FF5000333B3 /* ArcGISToolkitTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = ArcGISToolkitTests.xctest; - remoteRef = 4C8C80BB23AC3FF5000333B3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 97466015234265F6008EF35A /* ArcGISToolkit.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = ArcGISToolkit.framework; - remoteRef = 97466014234265F6008EF35A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 3E23A9DE1AFC28F6002E2214 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -4831,6 +4751,7 @@ 092A1C2722456D9500C5F230 /* DisplayWFS.storyboard in Resources */, F1F62C4422E65E0900EFD599 /* militaryoverlay.geodatabase in Resources */, 3EBA254A1D300FB500AB0703 /* SimpleRenderer.storyboard in Resources */, + 0083AA192628ED18003A28C8 /* ProgressViewController.xib in Resources */, D97B7E5F1FD9BFE700E1239D /* Subdivisions.cpg in Resources */, 3ED028B81B8E3A9800ACA70D /* SublayerVisibility.storyboard in Resources */, 3E8A05BA1ECD07DD0032231C /* SceneLayerURL.storyboard in Resources */, @@ -4960,6 +4881,7 @@ 00ADC3BD2464D45C00A3B88D /* AnimateImagesWithImageOverlay.storyboard in Resources */, 3E8A25911D36B97A00D14F08 /* MapLoaded.storyboard in Resources */, F14A8F012474AD9D00242D96 /* ConfigureSubnetworkTrace.storyboard in Resources */, + F11CED73256C857B002A3F56 /* ShowLabelsOnLayer3D.storyboard in Resources */, C7E9D7C821C0500300E6C47E /* Buffer.storyboard in Resources */, F1E8F0B12537D6DD000B9A0F /* NavigateRouteWithRerouting.storyboard in Resources */, 3ED028E91B8E3AA500ACA70D /* FLQuery.storyboard in Resources */, @@ -4981,7 +4903,6 @@ F1F651AC2498485C006DF277 /* ShowPopup.storyboard in Resources */, 00D4E8DE241AA18E002689DB /* ConvexHull.storyboard in Resources */, 4CCA30CF22399A91009D2AEF /* AddIntegratedMeshLayer.storyboard in Resources */, - 3E4B05F81B39EF250072E514 /* SVProgressHUD.bundle in Resources */, 3ED75D031ED39EDF009B1F75 /* FindServiceAreaInteractive.storyboard in Resources */, 3EABC7C21DB191BC00C161C6 /* Shasta_Elevation.tif in Resources */, 3E1183DF1ECF5A1000180152 /* Pyrenees.csv in Resources */, @@ -5195,6 +5116,7 @@ 00A3766A256C932800EC433A /* AppSecrets.swift.masque in Sources */, C7E86C9121751D1E001C65C3 /* UIViewController.swift in Sources */, 4CCA30C822386429009D2AEF /* ViewPointCloudDataOfflineViewController.swift in Sources */, + F11CED6D256C849A002A3F56 /* ShowLabelsOnLayer3DViewController.swift in Sources */, 3EABC7921DB1772000C161C6 /* RGBRendererSettingsViewController.swift in Sources */, 4CCE7BD620D2BD34001238F5 /* DistanceMeasurementAnalysisViewController.swift in Sources */, 3E39F6D41B9790A9000DEC6C /* FeatureTemplatePickerViewController.swift in Sources */, @@ -5278,7 +5200,6 @@ 9D5EDFE3230741670019C46A /* PreplannedMapAreaTableViewCell.swift in Sources */, 003D256C2513F4A6007527C2 /* AddENCExchangeSetViewController.swift in Sources */, 3ED028B71B8E3A9800ACA70D /* SublayersTableViewController.swift in Sources */, - 4C72117320BF4457004A7DD9 /* SVRadialGradientLayer.m in Sources */, 3EEB2B991EB9695F00B52513 /* RelatedFeaturesListViewController.swift in Sources */, 3E5E094E1EF850BA00FF3454 /* ManageSublayersViewController.swift in Sources */, 3E71621F1BA0D7ED008DE398 /* GraphicsWithSymbolsViewController.swift in Sources */, @@ -5291,7 +5212,6 @@ E45991A11EF3021D0089E9FD /* SearchForWebmapByKeywordViewController.swift in Sources */, 3ED028581B8E3A8500ACA70D /* CreateSaveMapViewController.swift in Sources */, 3E8A25841D36B6E300D14F08 /* FeatureLayerGDBViewController.swift in Sources */, - 4C72117020BF444C004A7DD9 /* SVProgressAnimatedView.m in Sources */, 0023F98025E717AC006B574E /* SimulatedNMEADataSource.swift in Sources */, 127E11D81FD0C3F8002CBD12 /* WMTSLayerViewController.swift in Sources */, 4CE15D4C22F37A2D005F2968 /* ControlAnnotationSublayerVisibilityViewController.swift in Sources */, @@ -5330,7 +5250,6 @@ 3EF024E91ECBC10600166EC5 /* FormatCoordinatesViewController.swift in Sources */, 3E85263D1B90DE2C00690EBD /* DisplayMapViewController.swift in Sources */, 3ED029681B8E3ACD00ACA70D /* UpdateAttributesOptionsViewController.swift in Sources */, - 3E4B05F91B39EF250072E514 /* SVProgressHUD.m in Sources */, 4CECF8A121D57F4000A56161 /* SetMinMaxScaleViewController.swift in Sources */, 3EBA25631D3417B000AB0703 /* SimpleMarkerSymbolViewController.swift in Sources */, 3E81C1BB1D8A17B600470AA4 /* VectorStylesViewController.swift in Sources */, @@ -5453,7 +5372,6 @@ 4CF6DF1B22F2058300A3092A /* HonorMobileMapPackageExpirationDateViewController.swift in Sources */, C7B29EBE218B8FEA004E5DE4 /* OpenMapURLSettingsViewController.swift in Sources */, 3ECDD9B01E8470E100E645AB /* DownloadProgressView.swift in Sources */, - 3E4B05F71B39EF250072E514 /* SVIndefiniteAnimatedView.m in Sources */, 3ED028741B8E3A8500ACA70D /* MapViewDrawStatusViewController.swift in Sources */, D90407941FD8608A00BFE07B /* RasterLayerGPKGViewController.swift in Sources */, 4C060E632260E9F90070C787 /* GenerateOfflineMapBasemapByReferenceViewController.swift in Sources */, @@ -5462,6 +5380,7 @@ 3EE692021B03D22500C167B8 /* Category.swift in Sources */, 3ED028E51B8E3AA500ACA70D /* DefinitionExpressionViewController.swift in Sources */, E4477CBE20EC0CCD004E14F9 /* ListTransformationsViewController.swift in Sources */, + 0083AA1A2628ED18003A28C8 /* ProgressViewController.swift in Sources */, 3E412B431D0B2FAD00349155 /* AppInfoViewController.swift in Sources */, 12D66036226697320005DE8A /* GroupLayersViewController.swift in Sources */, F1E4B11122D6AF5D005FDB4D /* ColormapRendererViewController.swift in Sources */, @@ -5514,11 +5433,6 @@ target = 3E23A9DF1AFC28F6002E2214 /* ArcGIS Runtime SDK Samples */; targetProxy = 4CD2B5592142EAF900767D87 /* PBXContainerItemProxy */; }; - 9746601E234266A3008EF35A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ArcGISToolkit; - targetProxy = 9746601D234266A3008EF35A /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -5571,7 +5485,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -5622,7 +5536,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -5645,17 +5559,17 @@ EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES; ENABLE_BITCODE = YES; INFOPLIST_FILE = "arcgis-ios-sdk-samples/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 100.10.0; + MARKETING_VERSION = 100.11.0; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "arcgis-ios-sdk-samples/Content Display Logic/Samples-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Debug; @@ -5674,17 +5588,17 @@ EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES; ENABLE_BITCODE = YES; INFOPLIST_FILE = "arcgis-ios-sdk-samples/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 100.10.0; + MARKETING_VERSION = 100.11.0; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "arcgis-ios-sdk-samples/Content Display Logic/Samples-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; @@ -5779,6 +5693,25 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Esri/arcgis-runtime-toolkit-ios"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 100.11.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 006A7869262F9F15001D2A5E /* ArcGISToolkit */ = { + isa = XCSwiftPackageProductDependency; + package = 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */; + productName = ArcGISToolkit; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 3E23A9D81AFC28F6002E2214 /* Project object */; } diff --git a/arcgis-ios-sdk-samples/Analysis/Analyze hotspots/AnalyzeHotspotsViewController.swift b/arcgis-ios-sdk-samples/Analysis/Analyze hotspots/AnalyzeHotspotsViewController.swift index 348d215a4..77830fdd2 100644 --- a/arcgis-ios-sdk-samples/Analysis/Analyze hotspots/AnalyzeHotspotsViewController.swift +++ b/arcgis-ios-sdk-samples/Analysis/Analyze hotspots/AnalyzeHotspotsViewController.swift @@ -71,10 +71,10 @@ class AnalyzeHotspotsViewController: UIViewController, HotspotSettingsViewContro // start job geoprocessingJob.start(statusHandler: { (status: AGSJobStatus) in // show progress hud with job status - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (result: AGSGeoprocessingResult?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } if let error = error { // show error diff --git a/arcgis-ios-sdk-samples/Analysis/Viewshed (geoprocessing)/ViewshedGeoprocessingViewController.swift b/arcgis-ios-sdk-samples/Analysis/Viewshed (geoprocessing)/ViewshedGeoprocessingViewController.swift index e3721bdf6..c95693cf3 100644 --- a/arcgis-ios-sdk-samples/Analysis/Viewshed (geoprocessing)/ViewshedGeoprocessingViewController.swift +++ b/arcgis-ios-sdk-samples/Analysis/Viewshed (geoprocessing)/ViewshedGeoprocessingViewController.swift @@ -83,12 +83,12 @@ class ViewshedGeoprocessingViewController: UIViewController, AGSGeoViewTouchDele newFeature.geometry = point // show progress hud - SVProgressHUD.show(withStatus: "Adding Feature") + UIApplication.shared.showProgressHUD(message: "Adding Feature") // add the new feature to the feature collection table featureCollectionTable.add(newFeature) { [weak self] (error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { // show error @@ -114,10 +114,10 @@ class ViewshedGeoprocessingViewController: UIViewController, AGSGeoViewTouchDele // start the job geoprocessingJob.start(statusHandler: { (status: AGSJobStatus) in // show progress hud with job status - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (result: AGSGeoprocessingResult?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return diff --git a/arcgis-ios-sdk-samples/AppDelegate.swift b/arcgis-ios-sdk-samples/AppDelegate.swift index c8371af9c..67c2cbaa8 100644 --- a/arcgis-ios-sdk-samples/AppDelegate.swift +++ b/arcgis-ios-sdk-samples/AppDelegate.swift @@ -25,14 +25,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele var categoryBrowserViewController: ContentCollectionViewController { return (splitViewController.viewControllers.first as! UINavigationController).viewControllers.first as! ContentCollectionViewController } - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - if url.absoluteString.range(of: "auth", options: [], range: nil, locale: nil) != nil { - AGSApplicationDelegate.shared().application(app, open: url, options: options) - } - return true - } - + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { // Override point for customization after application launch. let splitViewController = self.window!.rootViewController as! UISplitViewController @@ -55,33 +48,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele // Enable/disable touches based on settings. self.setTouchPref() - SVProgressHUD.setDefaultMaskType(.gradient) - // Uncomment the following line to set license key. // application.license() return true } - + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. self.setTouchPref() } - + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @@ -103,25 +94,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele // MARK: - Appearance modification func modifyAppearance() { + let navigationBarAppearance = UINavigationBarAppearance() + navigationBarAppearance.configureWithTransparentBackground() + navigationBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white] + navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white] + navigationBarAppearance.backgroundColor = .accentColor + let navigationBarAppearanceProxy = UINavigationBar.appearance() - if #available(iOS 13.0, *) { - let navigationBarAppearance = UINavigationBarAppearance() - navigationBarAppearance.configureWithTransparentBackground() - navigationBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white] - navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white] - navigationBarAppearance.backgroundColor = .accentColor - - navigationBarAppearanceProxy.standardAppearance = navigationBarAppearance - navigationBarAppearanceProxy.compactAppearance = navigationBarAppearance - navigationBarAppearanceProxy.scrollEdgeAppearance = navigationBarAppearance - } else { - navigationBarAppearanceProxy.largeTitleTextAttributes = [.foregroundColor: UIColor.white] - navigationBarAppearanceProxy.titleTextAttributes = [.foregroundColor: UIColor.white] - navigationBarAppearanceProxy.barTintColor = .accentColor - } - UISwitch.appearance().onTintColor = .accentColor + navigationBarAppearanceProxy.standardAppearance = navigationBarAppearance + navigationBarAppearanceProxy.compactAppearance = navigationBarAppearance + navigationBarAppearanceProxy.scrollEdgeAppearance = navigationBarAppearance navigationBarAppearanceProxy.tintColor = .white + + UISwitch.appearance().onTintColor = .accentColor UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .accentColor + if #available(iOS 14.0, *) { // Nothing to do! iOS 14 handles global tint with accent color. } else { @@ -133,9 +120,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele UIButton.appearance(whenContainedInInstancesOf: [AGSCallout.self]).tintColor = .accentColor } } - + // MARK: - Split view - + func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { if secondaryViewController.restorationIdentifier == "DetailNavigationController" { return true diff --git a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARNavigatorViewController.swift b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARNavigatorViewController.swift index dcfd1615e..cc771fdc2 100644 --- a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARNavigatorViewController.swift +++ b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARNavigatorViewController.swift @@ -159,7 +159,8 @@ class NavigateARNavigatorViewController: UIViewController { @IBAction func startTurnByTurn(_ sender: UIBarButtonItem) { routeTracker = AGSRouteTracker(routeResult: routeResult, routeIndex: 0, skipCoincidentStops: true) if routeTask.routeTaskInfo().supportsRerouting { - routeTracker?.enableRerouting(with: routeTask, routeParameters: routeParameters, strategy: .toNextStop, visitFirstStopOnStart: true ) { [weak self] (error: Error?) in + let reroutingParameters = AGSReroutingParameters(routeTask: routeTask, routeParameters: routeParameters)! + routeTracker?.enableRerouting(with: reroutingParameters) { [weak self] error in if let error = error { self?.presentAlert(error: error) } else { diff --git a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARRoutePlannerViewController.swift b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARRoutePlannerViewController.swift index b92d2774a..555c141c3 100644 --- a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARRoutePlannerViewController.swift +++ b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/NavigateARRoutePlannerViewController.swift @@ -38,8 +38,8 @@ class NavigateARRoutePlannerViewController: UIViewController { // MARK: Instance properties - /// The route task that solves the route using the online routing service, with authentication required. - let routeTask = AGSRouteTask(url: URL(string: "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World")!) + /// The route task that solves the route using the online routing service, using API key authentication. + let routeTask = AGSRouteTask(url: URL(string: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World")!) /// The parameters for route task to solve a route. var routeParameters: AGSRouteParameters! /// The data source to track device location and provide updates to location display. @@ -56,13 +56,6 @@ class NavigateARRoutePlannerViewController: UIViewController { return overlay }() - /// An OAuth2 configuration to access online routing service. - let oAuthConfiguration = AGSOAuthConfiguration( - portalURL: URL(string: "https://www.arcgis.com")!, - clientID: "lgAdHkYZYlwwfAhC", - redirectURL: "my-ags-app://auth" - ) - /// An `AGSPoint` representing the start of navigation. var startPoint: AGSPoint? { didSet { @@ -156,10 +149,6 @@ class NavigateARRoutePlannerViewController: UIViewController { // Avoid overlapping status label and map content. mapView.contentInset.top = 2 * statusLabel.font.lineHeight - // Configure the authentication manager to show the OAuth dialog. - AGSAuthenticationManager.shared().delegate = self - AGSAuthenticationManager.shared().oAuthConfigurations.add(oAuthConfiguration) - routeTask.load { [weak self] (error: Error?) in guard let self = self else { return } if let error = error { @@ -199,11 +188,6 @@ class NavigateARRoutePlannerViewController: UIViewController { } } } - - deinit { - AGSAuthenticationManager.shared().oAuthConfigurations.remove(oAuthConfiguration) - AGSAuthenticationManager.shared().credentialCache.removeAllCredentials() - } } // MARK: - Set route start and end on touch @@ -226,16 +210,3 @@ extension NavigateARRoutePlannerViewController: AGSGeoViewTouchDelegate { } } } - -// MARK: - Show OAuth dialog for route service - -extension NavigateARRoutePlannerViewController: AGSAuthenticationManagerDelegate { - func authenticationManager( _ authenticationManager: AGSAuthenticationManager, wantsToShow viewController: UIViewController) { - viewController.modalPresentationStyle = .overFullScreen - present(viewController, animated: true) - } - - func authenticationManager(_ authenticationManager: AGSAuthenticationManager, wantsToDismiss viewController: UIViewController) { - dismiss(animated: true) - } -} diff --git a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/README.md b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/README.md index 8f9b486c5..66ef3fd01 100644 --- a/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/README.md +++ b/arcgis-ios-sdk-samples/Augmented reality/Navigate in AR/README.md @@ -50,15 +50,19 @@ When you start, route instructions will be displayed and spoken. As you proceed ## About the data -This sample uses Esri's [World Elevation](https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer) service to ensure that route lines are placed appropriately in 3D space. It uses Esri's [World Route](https://www.arcgis.com/home/item.html?id=1feb41652c5c4bd2ba5c60df2b4ea2c4) service to calculate routes. The world routing service requires authentication and does consume ArcGIS Online credits. +This sample uses Esri's [World Elevation](https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer) service to ensure that route lines are placed appropriately in 3D space. It uses Esri's [World Route](https://www.arcgis.com/home/item.html?id=1feb41652c5c4bd2ba5c60df2b4ea2c4) service to calculate routes. -**Note:** This item requires an ArcGIS Online organizational subscription or an ArcGIS Developer account and consumes credits. +**Note:** This routing service requires one of the following authentication methods: -To access this sample, you'll need to do one of the following: +* An ArcGIS Online organizational subscription and credits +* An ArcGIS Developer account and credits +* An API key -* Sign in with an account that is a member of an organizational subscription. -* Sign in with a developer account. -* Register an application and use your application's credentials. +To access the routing service with ArcGIS identity/named user login using OAuth workflow, please read more at [ArcGIS Identity](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/). + +The routing service can also be accessed with an API key. Please read more at [API keys](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/api-keys/). + +Learn more about [security and authentication on ArcGIS Developers website](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/). ## Additional information diff --git a/arcgis-ios-sdk-samples/Cloud and portal/Integrated Windows Authentication/IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift b/arcgis-ios-sdk-samples/Cloud and portal/Integrated Windows Authentication/IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift index 7d1eeda66..ad5d17f4d 100644 --- a/arcgis-ios-sdk-samples/Cloud and portal/Integrated Windows Authentication/IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift +++ b/arcgis-ios-sdk-samples/Cloud and portal/Integrated Windows Authentication/IntegratedWindowsAuthenticationPortalMapBrowserViewController.swift @@ -92,7 +92,7 @@ class IntegratedWindowsAuthenticationPortalMapBrowserViewController: UITableView /// Shows an activity indicator in the center of the table view. func showActivityIndicator() { - let activityIndicatorView = UIActivityIndicatorView(style: .gray) + let activityIndicatorView = UIActivityIndicatorView(style: .medium) activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false activityIndicatorView.startAnimating() diff --git a/arcgis-ios-sdk-samples/Cloud and portal/List portal group users/GroupUsersViewController.swift b/arcgis-ios-sdk-samples/Cloud and portal/List portal group users/GroupUsersViewController.swift index 71a954e0a..af4432a22 100644 --- a/arcgis-ios-sdk-samples/Cloud and portal/List portal group users/GroupUsersViewController.swift +++ b/arcgis-ios-sdk-samples/Cloud and portal/List portal group users/GroupUsersViewController.swift @@ -41,14 +41,14 @@ class GroupUsersViewController: UIViewController, UITableViewDataSource, UITable private func loadPortalGroup() { // show progress hud - SVProgressHUD.show(withStatus: "Loading Portal Group") + UIApplication.shared.showProgressHUD(message: "Loading Portal Group") // query group based on owner and title let queryParams = AGSPortalQueryParameters(forGroupsWithOwner: "ArcGISRuntimeSDK", title: "Runtime Group") // find groups with using query params self.portal.findGroups(with: queryParams) { [weak self] (resultSet: AGSPortalQueryResultSet?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -73,11 +73,11 @@ class GroupUsersViewController: UIViewController, UITableViewDataSource, UITable private func fetchGroupUsers() { // show progress hud - SVProgressHUD.show(withStatus: "Fetching Users") + UIApplication.shared.showProgressHUD(message: "Fetching Users") // fetch users in group self.portalGroup.fetchUsers { [weak self] (users, _, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -102,12 +102,12 @@ class GroupUsersViewController: UIViewController, UITableViewDataSource, UITable private func loadAllUsers() { // show progress hud - SVProgressHUD.show(withStatus: "Loading User Data") + UIApplication.shared.showProgressHUD(message: "Loading User Data") // load user data AGSLoadObjects(portalUsers) { [weak self] (success) in // dismiss hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if success { // reload table view diff --git a/arcgis-ios-sdk-samples/Cloud and portal/Search for webmap by keyword/SearchForWebmapByKeywordViewController.swift b/arcgis-ios-sdk-samples/Cloud and portal/Search for webmap by keyword/SearchForWebmapByKeywordViewController.swift index 764916508..589d57f01 100644 --- a/arcgis-ios-sdk-samples/Cloud and portal/Search for webmap by keyword/SearchForWebmapByKeywordViewController.swift +++ b/arcgis-ios-sdk-samples/Cloud and portal/Search for webmap by keyword/SearchForWebmapByKeywordViewController.swift @@ -38,19 +38,7 @@ class SearchForWebmapByKeywordViewController: UICollectionViewController { (navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["SearchForWebmapByKeywordViewController", "WebMapCell", "WebMapViewController"] - if #available(iOS 13, *) { - // for iOS 13 this must be added in viewDidLoad - // for iOS 12, it gets added in viewDidAppear, because for iOS 12 it doesn't - // show up if added here. - addSearchController() - } - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - if navigationItem.searchController == nil { - addSearchController() - } + addSearchController() } private func addSearchController() { @@ -66,31 +54,11 @@ class SearchForWebmapByKeywordViewController: UICollectionViewController { let searchBar = searchController.searchBar searchBar.autocapitalizationType = .none - if #available(iOS 13, *) { - // Change the backgroundColor to differentiate from nav bar color. - searchBar.searchTextField.backgroundColor = .tertiarySystemBackground - // Set the color of the insertion cursor as well as the text. The text is default to black color whereas the cursor is white. - searchBar.searchTextField.tintColor = .label - } else { - // This code is required to make the search bar look decent on iOS 12 - // This does not work on iOS 13, where the search bar looks different. - // Different meaning - not as good as iOS 12 looks like with this fix, - // but at least acceptable and a bit better than what it would look like - // on 12 without this fix. - // Set the color of "Cancel" text, to mimic the settings on iOS 12. On iOS 13 it is default to white. - searchBar.tintColor = .white - - // find the text field to customize its appearance - if let textfield = searchBar.value(forKey: "searchField") as? UITextField { - // set the color of the insertion cursor - textfield.tintColor = UIColor.darkText - if let backgroundview = textfield.subviews.first { - backgroundview.backgroundColor = UIColor.white - backgroundview.layer.cornerRadius = 12 - backgroundview.clipsToBounds = true - } - } - } + // Change the backgroundColor to differentiate from nav bar color. + searchBar.searchTextField.backgroundColor = .tertiarySystemBackground + // Set the color of the insertion cursor as well as the text. + // The text is default to black color whereas the cursor is white. + searchBar.searchTextField.tintColor = .label // embed the search bar under the title in the navigation bar navigationItem.searchController = searchController diff --git a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist index dd8a62c5f..6acbc58da 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist +++ b/arcgis-ios-sdk-samples/Content Display Logic/ContentPList.plist @@ -1781,6 +1781,14 @@ descriptionText Show realistic lighting and shadows for a given time of day. + + displayName + Show labels on layer in 3D + storyboardName + ShowLabelsOnLayer3D + descriptionText + Display custom labels in a 3D scene. + diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/ContentCollectionViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/ContentCollectionViewController.swift index d1ec88947..b6e592a0e 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/ContentCollectionViewController.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/ContentCollectionViewController.swift @@ -44,42 +44,22 @@ class ContentCollectionViewController: UICollectionViewController, UICollectionV let searchBar = searchController.searchBar searchBar.autocapitalizationType = .none - if #available(iOS 13, *) { - // Change the backgroundColor to differentiate from nav bar color. - searchBar.searchTextField.backgroundColor = .tertiarySystemBackground - // Set the color of the insertion cursor as well as the text. The text is default to black color whereas the cursor is white. - searchBar.searchTextField.tintColor = .label - } else { - // This code is required to make the search bar look decent on iOS 12 - // This does not work on iOS 13, where the search bar looks different. - // Different meaning - not as good as iOS 12 looks like with this fix, - // but at least acceptable and a bit better than what it would look like - // on 12 without this fix. - // Set the color of "Cancel" text, to mimic the settings on iOS 12. On iOS 13 it is default to white. - searchBar.tintColor = .white - - // find the text field to customize its appearance - if let textfield = searchBar.value(forKey: "searchField") as? UITextField { - // set the color of the insertion cursor - textfield.tintColor = UIColor.darkText - if let backgroundview = textfield.subviews.first { - backgroundview.backgroundColor = UIColor.white - backgroundview.layer.cornerRadius = 12 - backgroundview.clipsToBounds = true - } - } - } + // Change the backgroundColor to differentiate from nav bar color. + searchBar.searchTextField.backgroundColor = .tertiarySystemBackground + // Set the color of the insertion cursor as well as the text. + // The text is default to black color whereas the cursor is white. + searchBar.searchTextField.tintColor = .label // embed the search bar under the title in the navigation bar navigationItem.searchController = searchController } - + // MARK: UICollectionViewDataSource - + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return categories.count } - + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as! CategoryCell diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.swift new file mode 100644 index 000000000..c2b206bb6 --- /dev/null +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.swift @@ -0,0 +1,156 @@ +// 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 + +extension UIViewController: GlobalProgressDisplayable { + var window: UIWindow? { view.window } +} + +extension UIApplication: GlobalProgressDisplayable { + var window: UIWindow? { windows.first } +} + +protocol GlobalProgressDisplayable { + var window: UIWindow? { get } +} + +extension GlobalProgressDisplayable { + func showProgressHUD(message: String, duration: TimeInterval? = nil) { + GlobalProgress.shared.showProgress(message: message, duration: duration, window: window, animated: true) + } + func showErrorHUD(error: Error, duration: TimeInterval = 2.0) { + GlobalProgress.shared.showProgress(message: error.localizedDescription, duration: duration, window: window, animated: false) + } + func hideProgressHUD() { + GlobalProgress.shared.hideProgress() + } +} + +private class GlobalProgress { + static let shared = GlobalProgress() + + private init() { } + + private var alertWindow: UIWindow? + + private var timer: Timer? + + func showProgress(message: String, duration: TimeInterval?, window: UIWindow?, animated: Bool) { + // Invalidate old timer, if one exists. + if let timer = timer { + timer.invalidate() + self.timer = nil + } + // Update existing progress if already presented. + if let alertWindow = alertWindow { + (alertWindow.rootViewController as! PhantomViewController).progressViewController.label.text = message + } else { + let progressWindow = UIWindow(frame: window?.frame ?? UIScreen.main.bounds) + let progressViewController = ProgressViewController() + progressViewController.loadViewIfNeeded() + progressViewController.label.text = message + let phantom = PhantomViewController(progressViewController: progressViewController) + progressWindow.rootViewController = phantom + progressWindow.windowLevel = .alert + 1 + progressWindow.makeKeyAndVisible() + alertWindow = progressWindow + } + // Create a timer to dismiss if a duration is set. + if let duration = duration { + timer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { [unowned self] _ in + self.timer = nil + self.hideProgress() + } + } + } + + func hideProgress() { + guard let window = alertWindow, + let phantom = window.rootViewController as? PhantomViewController + else { return } + + phantom.progressViewController.dismiss(animated: true) { + guard let alertWindow = self.alertWindow else { return } + alertWindow.resignKey() + self.alertWindow = nil + } + } +} + +private class ProgressViewController: UIViewController { + @IBOutlet var label: UILabel! + @IBOutlet var activityView: UIActivityIndicatorView! + + init() { + super.init(nibName: "ProgressViewController", bundle: Bundle.main) + view.backgroundColor = backgroundColor(for: traitCollection.userInterfaceStyle) + } + + @available(*, unavailable) + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + fatalError("init(nibName:bundle:) has not been implemented") + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + view.backgroundColor = backgroundColor(for: traitCollection.userInterfaceStyle) + } + + func backgroundColor(for userInterfaceStyle: UIUserInterfaceStyle) -> UIColor { + let backgroundColor: UIColor + switch userInterfaceStyle { + case .dark: + backgroundColor = UIColor.black.withAlphaComponent(0.48) + default: + backgroundColor = UIColor.black.withAlphaComponent(0.2) + } + return backgroundColor + } +} + +private class PhantomViewController: UIViewController { + let progressViewController: ProgressViewController + + // MARK: - Init + + init(progressViewController: ProgressViewController) { + self.progressViewController = progressViewController + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + fatalError("init(nibName:bundle:) has not been implemented") + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Lifecycle + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + progressViewController.modalTransitionStyle = .crossDissolve + progressViewController.modalPresentationStyle = .overFullScreen + present(progressViewController, animated: true) + } +} diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.xib b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.xib new file mode 100644 index 000000000..e4d7984a3 --- /dev/null +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/Progress View Controller/ProgressViewController.xib @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift index 8828fc1ab..c981be9ae 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Controllers/SourceCodeViewController.swift @@ -23,11 +23,7 @@ class SourceCodeViewController: UIViewController, UIAdaptivePresentationControll @IBOutlet var toolbarTitleButton: UIBarButtonItem! { didSet { if filenames.count <= 1 { - if #available(iOS 13.0, *) { - toolbarTitleButton.tintColor = UIColor.label - } else { - toolbarTitleButton.tintColor = UIColor.black - } + toolbarTitleButton.tintColor = .label } toolbarTitleButton.possibleTitles = Set(filenames) } diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Samples-Bridging-Header.h b/arcgis-ios-sdk-samples/Content Display Logic/Samples-Bridging-Header.h deleted file mode 100644 index 458d831f3..000000000 --- a/arcgis-ios-sdk-samples/Content Display Logic/Samples-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "SVProgressHUD.h" diff --git a/arcgis-ios-sdk-samples/Content Display Logic/Views/DownloadProgressView.swift b/arcgis-ios-sdk-samples/Content Display Logic/Views/DownloadProgressView.swift index c3f2b82af..9d9ffab1b 100644 --- a/arcgis-ios-sdk-samples/Content Display Logic/Views/DownloadProgressView.swift +++ b/arcgis-ios-sdk-samples/Content Display Logic/Views/DownloadProgressView.swift @@ -129,7 +129,7 @@ class DownloadProgressView: UIView { private func show() { self.frame = UIScreen.main.bounds - if let newWindow = UIApplication.shared.keyWindow { + if let newWindow = UIApplication.shared.windows.first(where: \.isKeyWindow) { newWindow.addSubview(self) } } diff --git a/arcgis-ios-sdk-samples/Edit data/Add features (feature service)/AddFeaturesViewController.swift b/arcgis-ios-sdk-samples/Edit data/Add features (feature service)/AddFeaturesViewController.swift index c90a4b9c3..573f331fb 100644 --- a/arcgis-ios-sdk-samples/Edit data/Add features (feature service)/AddFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Add features (feature service)/AddFeaturesViewController.swift @@ -56,11 +56,11 @@ class AddFeaturesViewController: UIViewController, AGSGeoViewTouchDelegate { let feature = featureTable.createFeature(attributes: featureAttributes, geometry: normalizedGeometry) // show the progress hud - SVProgressHUD.show(withStatus: "Adding..") + UIApplication.shared.showProgressHUD(message: "Adding..") // add the feature to the feature table featureTable.add(feature) { [weak self] (error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(message: "Error while adding feature: \(error.localizedDescription)") @@ -82,7 +82,7 @@ class AddFeaturesViewController: UIViewController, AGSGeoViewTouchDelegate { featureEditResults.first?.completedWithErrors == false { self?.presentAlert(message: "Edits applied successfully") } - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } diff --git a/arcgis-ios-sdk-samples/Edit data/Edit and sync features/EditAndSyncFeaturesViewController.swift b/arcgis-ios-sdk-samples/Edit data/Edit and sync features/EditAndSyncFeaturesViewController.swift index d7645d6ee..2ea8ddafc 100644 --- a/arcgis-ios-sdk-samples/Edit data/Edit and sync features/EditAndSyncFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Edit and sync features/EditAndSyncFeaturesViewController.swift @@ -174,10 +174,10 @@ class EditAndSyncFeaturesViewController: UIViewController { self.generateJob = generateGeodatabaseJob generateGeodatabaseJob.start( statusHandler: { (status: AGSJobStatus) in - SVProgressHUD.show(withStatus: status.statusString()) // Show job status. + UIApplication.shared.showProgressHUD(message: status.statusString()) // Show job status. }, completion: { [weak self] (_, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) } else { @@ -212,9 +212,9 @@ class EditAndSyncFeaturesViewController: UIViewController { let syncGeodatabaseJob = geodatabaseSyncTask.syncJob(with: syncGeodatabaseParameters, geodatabase: geodatabase) self.syncJob = syncGeodatabaseJob syncGeodatabaseJob.start(statusHandler: { (status: AGSJobStatus) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (_: [AGSSyncLayerResult]?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) } else { diff --git a/arcgis-ios-sdk-samples/Edit data/Edit feature attachments/AttachmentsTableViewController.swift b/arcgis-ios-sdk-samples/Edit data/Edit feature attachments/AttachmentsTableViewController.swift index 5a841bb1a..1820b7476 100644 --- a/arcgis-ios-sdk-samples/Edit data/Edit feature attachments/AttachmentsTableViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Edit feature attachments/AttachmentsTableViewController.swift @@ -26,11 +26,11 @@ class AttachmentsTableViewController: UITableViewController { private func loadAttachments() { // show progress hud - SVProgressHUD.show(withStatus: "Loading attachments") + UIApplication.shared.showProgressHUD(message: "Loading attachments") feature?.fetchAttachments { [weak self] (attachments: [AGSAttachment]?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -64,10 +64,10 @@ class AttachmentsTableViewController: UITableViewController { } private func downloadImage(for attachment: AGSAttachment) { - SVProgressHUD.show(withStatus: "Downloading attachment") + UIApplication.shared.showProgressHUD(message: "Downloading attachment") attachment.fetchData { [weak self] (data: Data?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -131,11 +131,11 @@ class AttachmentsTableViewController: UITableViewController { @IBAction func doneAction() { if let table = feature?.featureTable as? AGSServiceFeatureTable { // show progress hud - SVProgressHUD.show(withStatus: "Applying edits") + UIApplication.shared.showProgressHUD(message: "Applying edits") table.applyEdits { [weak self] (_, error) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -157,10 +157,10 @@ class AttachmentsTableViewController: UITableViewController { } // show progress hud - SVProgressHUD.show(withStatus: "Adding attachment") + UIApplication.shared.showProgressHUD(message: "Adding attachment") feature?.addAttachment(withName: "Attachment.png", contentType: "png", data: pngData) { [weak self] (attachment: AGSAttachment?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return diff --git a/arcgis-ios-sdk-samples/Edit data/Edit features (connected)/EditFeaturesOnlineViewController.swift b/arcgis-ios-sdk-samples/Edit data/Edit features (connected)/EditFeaturesOnlineViewController.swift index 1ed9cf492..ee5224bf0 100644 --- a/arcgis-ios-sdk-samples/Edit data/Edit features (connected)/EditFeaturesOnlineViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Edit features (connected)/EditFeaturesOnlineViewController.swift @@ -59,10 +59,10 @@ class EditFeaturesOnlineViewController: UIViewController, AGSGeoViewTouchDelegat func applyEdits() { // show progress hud - SVProgressHUD.show(withStatus: "Applying edits") + UIApplication.shared.showProgressHUD(message: "Applying edits") (featureLayer.featureTable as! AGSServiceFeatureTable).applyEdits { [weak self] (_, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(message: "Error while applying edits: \(error.localizedDescription)") diff --git a/arcgis-ios-sdk-samples/Edit data/Edit with branch versioning/EditWithBranchVersioningViewController.swift b/arcgis-ios-sdk-samples/Edit data/Edit with branch versioning/EditWithBranchVersioningViewController.swift index db0c3a8cd..18e23b4aa 100644 --- a/arcgis-ios-sdk-samples/Edit data/Edit with branch versioning/EditWithBranchVersioningViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Edit with branch versioning/EditWithBranchVersioningViewController.swift @@ -96,9 +96,9 @@ class EditWithBranchVersioningViewController: UIViewController { let serviceGeodatabase = AGSServiceGeodatabase(url: serviceURL) // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. serviceGeodatabase.credential = AGSCredential(user: "editor01", password: "S7#i2LWmYH75") - SVProgressHUD.show(withStatus: "Loading service geodatabase…") + UIApplication.shared.showProgressHUD(message: "Loading service geodatabase…") serviceGeodatabase.load { [weak self] error in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } if let error = error { self.presentAlert(error: error) @@ -129,9 +129,9 @@ class EditWithBranchVersioningViewController: UIViewController { func loadFeatureLayer(with featureTable: AGSFeatureTable, completion: @escaping (AGSFeatureLayer) -> Void) { let featureLayer = AGSFeatureLayer(featureTable: featureTable) - SVProgressHUD.show(withStatus: "Loading feature layer…") + UIApplication.shared.showProgressHUD(message: "Loading feature layer…") featureLayer.load { [weak self] error in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let extent = featureLayer.fullExtent { // Zoom to the target extent with animation. self?.mapView.setViewpoint(AGSViewpoint(targetExtent: extent), completion: nil) @@ -224,9 +224,9 @@ class EditWithBranchVersioningViewController: UIViewController { /// - completion: A closure to execute after edits are applied. func applyLocalEdits(geodatabase: AGSServiceGeodatabase, completion: @escaping () -> Void) { if geodatabase.hasLocalEdits() { - SVProgressHUD.show(withStatus: "Applying local edits…") + UIApplication.shared.showProgressHUD(message: "Applying local edits…") geodatabase.applyEdits { _, _ in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() completion() } } else { @@ -241,9 +241,9 @@ class EditWithBranchVersioningViewController: UIViewController { /// - completion: A closure to execute after edits are undone. func undoLocalEdits(geodatabase: AGSServiceGeodatabase, completion: @escaping () -> Void) { if geodatabase.hasLocalEdits() { - SVProgressHUD.show(withStatus: "Discarding local edits…") + UIApplication.shared.showProgressHUD(message: "Discarding local edits…") geodatabase.undoLocalEdits { _ in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() completion() } } else { diff --git a/arcgis-ios-sdk-samples/Edit data/Offline edit and sync/OfflineEditingViewController.swift b/arcgis-ios-sdk-samples/Edit data/Offline edit and sync/OfflineEditingViewController.swift index 5477f6ca0..87c23eb6d 100644 --- a/arcgis-ios-sdk-samples/Edit data/Offline edit and sync/OfflineEditingViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Offline edit and sync/OfflineEditingViewController.swift @@ -303,9 +303,9 @@ class OfflineEditingViewController: UIViewController { // Start the job. generateJob.start(statusHandler: { (status) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (object, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -369,9 +369,9 @@ class OfflineEditingViewController: UIViewController { let syncJob = syncTask.syncJob(with: params, geodatabase: generatedGeodatabase) self.syncJob = syncJob syncJob.start(statusHandler: { (status) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (_, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) @@ -410,10 +410,10 @@ class OfflineEditingViewController: UIViewController { extension OfflineEditingViewController: AGSGeoViewTouchDelegate { func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { - SVProgressHUD.show(withStatus: "Loading") + UIApplication.shared.showProgressHUD(message: "Loading") mapView.identifyLayers(atScreenPoint: screenPoint, tolerance: 12, returnPopupsOnly: false, maximumResultsPerLayer: 10) { [weak self] (results: [AGSIdentifyLayerResult]?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -482,10 +482,10 @@ extension OfflineEditingViewController: AGSPopupsViewControllerDelegate { // Sync changes if in service mode. if liveMode { // Tell the user edits are being saved int the background. - SVProgressHUD.show(withStatus: "Saving feature details...") + UIApplication.shared.showProgressHUD(message: "Saving feature details...") (feature.featureTable as! AGSServiceFeatureTable).applyEdits { [weak self] (_, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) diff --git a/arcgis-ios-sdk-samples/Edit data/Update attributes (feature service)/UpdateAttributesViewController.swift b/arcgis-ios-sdk-samples/Edit data/Update attributes (feature service)/UpdateAttributesViewController.swift index 3d5533169..9447ff1f8 100644 --- a/arcgis-ios-sdk-samples/Edit data/Update attributes (feature service)/UpdateAttributesViewController.swift +++ b/arcgis-ios-sdk-samples/Edit data/Update attributes (feature service)/UpdateAttributesViewController.swift @@ -60,10 +60,10 @@ class UpdateAttributesViewController: UIViewController, AGSGeoViewTouchDelegate, } func applyEdits() { - SVProgressHUD.show(withStatus: "Applying edits") + UIApplication.shared.showProgressHUD(message: "Applying edits") featureTable.applyEdits { [weak self] (_, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return @@ -125,11 +125,11 @@ class UpdateAttributesViewController: UIViewController, AGSGeoViewTouchDelegate, extension UpdateAttributesViewController: UpdateAttributesOptionsViewControllerDelegate { func optionsViewController(_ optionsViewController: UpdateAttributesOptionsViewController, didSelectOptionAtIndex index: Int) { self.dismiss(animated: true) - SVProgressHUD.show(withStatus: "Updating") + UIApplication.shared.showProgressHUD(message: "Updating") selectedFeature.attributes["typdamage"] = types[index] featureTable.update(selectedFeature) { [weak self] (error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) diff --git a/arcgis-ios-sdk-samples/Features/Add delete related features/AddDeleteRelatedFeaturesViewController.swift b/arcgis-ios-sdk-samples/Features/Add delete related features/AddDeleteRelatedFeaturesViewController.swift index d4b3f66fc..e8d2d9825 100644 --- a/arcgis-ios-sdk-samples/Features/Add delete related features/AddDeleteRelatedFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Add delete related features/AddDeleteRelatedFeaturesViewController.swift @@ -69,12 +69,12 @@ class AddDeleteRelatedFeaturesViewController: UIViewController, AGSGeoViewTouchD func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) { // show progress hud for identify - SVProgressHUD.show(withStatus: "Identifying feature") + UIApplication.shared.showProgressHUD(message: "Identifying feature") // identify features at tapped location self.mapView.identifyLayer(self.parksFeatureLayer, screenPoint: screenPoint, tolerance: 12, returnPopupsOnly: false) { [weak self] (result) in // hide progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = result.error { // show error to user 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..f51906ebb 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 @@ -44,7 +44,7 @@ class RelatedFeaturesViewController: UITableViewController { } // show progress hud - SVProgressHUD.show(withStatus: "Querying related features") + UIApplication.shared.showProgressHUD(message: "Querying related features") // keep for later use self.relationshipInfo = relationshipInfo @@ -58,7 +58,7 @@ class RelatedFeaturesViewController: UITableViewController { // query for species related to the selected park self.originFeatureTable.queryRelatedFeatures(for: self.originFeature, parameters: parameters) { [weak self] (results: [AGSRelatedFeatureQueryResult]?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) @@ -84,11 +84,11 @@ class RelatedFeaturesViewController: UITableViewController { feature.relate(to: self.originFeature) // show progress hud - SVProgressHUD.show(withStatus: "Adding feature") + UIApplication.shared.showProgressHUD(message: "Adding feature") // add new feature to related table relatedTable.add(feature) { [weak self] (error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) @@ -106,11 +106,11 @@ class RelatedFeaturesViewController: UITableViewController { } // show progress hud - SVProgressHUD.show(withStatus: "Deleting feature") + UIApplication.shared.showProgressHUD(message: "Deleting feature") // delete feature from related table relatedTable.delete(feature) { [weak self] (error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) @@ -128,10 +128,10 @@ class RelatedFeaturesViewController: UITableViewController { } // show progress hud - SVProgressHUD.show(withStatus: "Applying edits") + UIApplication.shared.showProgressHUD(message: "Applying edits") relatedTable.applyEdits { [weak self] (_, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { // show error diff --git a/arcgis-ios-sdk-samples/Features/Feature collection layer (query)/FeatureCollectionLayerQueryViewController.swift b/arcgis-ios-sdk-samples/Features/Feature collection layer (query)/FeatureCollectionLayerQueryViewController.swift index b5b4dba7f..3270fbc8e 100644 --- a/arcgis-ios-sdk-samples/Features/Feature collection layer (query)/FeatureCollectionLayerQueryViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Feature collection layer (query)/FeatureCollectionLayerQueryViewController.swift @@ -43,12 +43,12 @@ class FeatureCollectionLayerQueryViewController: UIViewController { queryParams.whereClause = "1=1" // show progress hud - SVProgressHUD.show(withStatus: "Querying") + UIApplication.shared.showProgressHUD(message: "Querying") // query feature from the table self.featureTable.queryFeatures(with: queryParams) { [weak self] (queryResult: AGSFeatureQueryResult?, error: Error?) in // hide progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { // show error diff --git a/arcgis-ios-sdk-samples/Features/Generate geodatabase/GenerateGeodatabaseViewController.swift b/arcgis-ios-sdk-samples/Features/Generate geodatabase/GenerateGeodatabaseViewController.swift index 5f38237dd..1c2a87d18 100644 --- a/arcgis-ios-sdk-samples/Features/Generate geodatabase/GenerateGeodatabaseViewController.swift +++ b/arcgis-ios-sdk-samples/Features/Generate geodatabase/GenerateGeodatabaseViewController.swift @@ -108,15 +108,15 @@ class GenerateGeodatabaseViewController: UIViewController { // kick off the job generateJob.start( statusHandler: { (status: AGSJobStatus) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, - completion: { [weak self] (object: AnyObject?, error: Error?) in - SVProgressHUD.dismiss() + completion: { [weak self] (geodatabase: AGSGeodatabase?, error: Error?) in + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) } else { - self?.generatedGeodatabase = object as? AGSGeodatabase + self?.generatedGeodatabase = geodatabase self?.displayLayersFromGeodatabase() } diff --git a/arcgis-ios-sdk-samples/Features/List related features/ListRelatedFeaturesViewController.swift b/arcgis-ios-sdk-samples/Features/List related features/ListRelatedFeaturesViewController.swift index c2e738ffe..f77dff27d 100644 --- a/arcgis-ios-sdk-samples/Features/List related features/ListRelatedFeaturesViewController.swift +++ b/arcgis-ios-sdk-samples/Features/List related features/ListRelatedFeaturesViewController.swift @@ -79,12 +79,12 @@ class ListRelatedFeaturesViewController: UIViewController, AGSGeoViewTouchDelega } // show progress hud - SVProgressHUD.show(withStatus: "Identifying feature") + UIApplication.shared.showProgressHUD(message: "Identifying feature") // identify features at the tapped location self.mapView.identifyLayer(self.parksFeatureLayer, screenPoint: screenPoint, tolerance: 12, returnPopupsOnly: false) { [weak self] (result: AGSIdentifyLayerResult) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = result.error { // dismiss progress hud @@ -110,12 +110,12 @@ class ListRelatedFeaturesViewController: UIViewController, AGSGeoViewTouchDelega // query for related features given the origin feature private func queryRelatedFeatures() { // show progress hud - SVProgressHUD.show(withStatus: "Querying related features") + UIApplication.shared.showProgressHUD(message: "Querying related features") // query for related features self.parksFeatureTable.queryRelatedFeatures(for: self.selectedPark) { [weak self] (results: [AGSRelatedFeatureQueryResult]?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } diff --git a/arcgis-ios-sdk-samples/Geometry/Project/Project.storyboard b/arcgis-ios-sdk-samples/Geometry/Project/Project.storyboard index 7f9960d5c..4cdab7683 100644 --- a/arcgis-ios-sdk-samples/Geometry/Project/Project.storyboard +++ b/arcgis-ios-sdk-samples/Geometry/Project/Project.storyboard @@ -1,9 +1,9 @@ - + - + @@ -43,19 +43,19 @@ diff --git a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRastersViewController.swift b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRastersViewController.swift index ff6afdb73..1a733c908 100644 --- a/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRastersViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/Apply mosaic rule to rasters/ApplyMosaicRuleToRastersViewController.swift @@ -30,7 +30,7 @@ class ApplyMosaicRuleToRastersViewController: UIViewController { // Observe the map view's drawing status to see when the new mosaic rule is loaded. drawStatusObservation = mapView.observe(\.drawStatus, options: .initial) { mapView, _ in if mapView.drawStatus == .completed { - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } @@ -85,11 +85,11 @@ class ApplyMosaicRuleToRastersViewController: UIViewController { let map = AGSMap(basemapStyle: .arcGISTopographic) // Add raster layer as an operational layer to the map. map.operationalLayers.add(rasterLayer) - SVProgressHUD.show(withStatus: "Loading") + UIApplication.shared.showProgressHUD(message: "Loading") rasterLayer.load { [weak self] error in guard let self = self else { return } if let error = error { - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() self.presentAlert(error: error) } else { // When loaded, set the map view's viewpoint to the image service raster's center. @@ -118,7 +118,7 @@ class ApplyMosaicRuleToRastersViewController: UIViewController { ) mosaicRulePairs.forEach { name, rule in let action = UIAlertAction(title: name, style: .default) { _ in - SVProgressHUD.show(withStatus: "Loading mosaic rule") + UIApplication.shared.showProgressHUD(message: "Loading mosaic rule") self.setStatus(message: "\(name) selected.") self.imageServiceRaster.mosaicRule = rule } diff --git a/arcgis-ios-sdk-samples/Layers/ArcGIS vector tiled layer (custom style)/VectorTileCustomStyleViewController.swift b/arcgis-ios-sdk-samples/Layers/ArcGIS vector tiled layer (custom style)/VectorTileCustomStyleViewController.swift index 8e831b714..6bc8f5e5c 100644 --- a/arcgis-ios-sdk-samples/Layers/ArcGIS vector tiled layer (custom style)/VectorTileCustomStyleViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/ArcGIS vector tiled layer (custom style)/VectorTileCustomStyleViewController.swift @@ -84,9 +84,9 @@ class VectorTileCustomStyleViewController: UIViewController { // Hold a strong reference to the job until it finishes. exportVectorTilesJob.start( statusHandler: { (status: AGSJobStatus) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] result, error in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } // De-reference the job. self.exportVectorTilesJob = nil diff --git a/arcgis-ios-sdk-samples/Layers/Browse WFS layers/WFSLayersTableViewController.swift b/arcgis-ios-sdk-samples/Layers/Browse WFS layers/WFSLayersTableViewController.swift index 2cba80df9..1d39ca218 100644 --- a/arcgis-ios-sdk-samples/Layers/Browse WFS layers/WFSLayersTableViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/Browse WFS layers/WFSLayersTableViewController.swift @@ -148,7 +148,7 @@ class WFSLayersTableViewController: UITableViewController { params.whereClause = "1=1" // Show progress - SVProgressHUD.show(withStatus: "Querying") + UIApplication.shared.showProgressHUD(message: "Querying") // Populate features based on query self.lastQuery = wfsFeatureTable.populateFromService(with: params, clearCache: true, outFields: ["*"]) { [weak self] (result: AGSFeatureQueryResult?, error: Error?) in @@ -182,7 +182,7 @@ class WFSLayersTableViewController: UITableViewController { } } // Hide Progress - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } diff --git a/arcgis-ios-sdk-samples/Layers/Display KML/DisplayKMLViewController.swift b/arcgis-ios-sdk-samples/Layers/Display KML/DisplayKMLViewController.swift index e9446af10..d431d2809 100644 --- a/arcgis-ios-sdk-samples/Layers/Display KML/DisplayKMLViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/Display KML/DisplayKMLViewController.swift @@ -92,13 +92,13 @@ class DisplayKMLViewController: UIViewController { mapView.map?.operationalLayers.add(kmlLayer) // Show the progress indicator - SVProgressHUD.show(withStatus: "Loading KML Layer") + UIApplication.shared.showProgressHUD(message: "Loading KML Layer") // This load call is not required, but it allows for error // feedback and progress indication kmlLayer.load { [weak self] (error) in // Close the progress indicator - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self?.presentAlert(error: error) diff --git a/arcgis-ios-sdk-samples/Layers/Display a WFS layer/DisplayWFSViewController.swift b/arcgis-ios-sdk-samples/Layers/Display a WFS layer/DisplayWFSViewController.swift index f270fdb63..01d1c860d 100644 --- a/arcgis-ios-sdk-samples/Layers/Display a WFS layer/DisplayWFSViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/Display a WFS layer/DisplayWFSViewController.swift @@ -78,7 +78,7 @@ class DisplayWFSViewController: UIViewController { params.spatialRelationship = .intersects // Show progress - SVProgressHUD.show(withStatus: "Querying") + UIApplication.shared.showProgressHUD(message: "Querying") // Populate features based on query self.lastQuery = self.wfsFeatureTable.populateFromService(with: params, clearCache: true, outFields: ["*"]) { [weak self] (result: AGSFeatureQueryResult?, error: Error?) in @@ -98,7 +98,7 @@ class DisplayWFSViewController: UIViewController { } } // Hide Progress - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } diff --git a/arcgis-ios-sdk-samples/Layers/Export tiles/ExportTilesViewController.swift b/arcgis-ios-sdk-samples/Layers/Export tiles/ExportTilesViewController.swift index fdd27e742..a02ebdcc9 100644 --- a/arcgis-ios-sdk-samples/Layers/Export tiles/ExportTilesViewController.swift +++ b/arcgis-ios-sdk-samples/Layers/Export tiles/ExportTilesViewController.swift @@ -131,9 +131,9 @@ class ExportTilesViewController: UIViewController { // Get and run the job. job = exportTask.exportTileCacheJob(with: parameters, downloadFileURL: downloadFileURL) job.start(statusHandler: { (status) in - SVProgressHUD.show(withStatus: status.statusString()) + UIApplication.shared.showProgressHUD(message: status.statusString()) }, completion: { [weak self] (result, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } self.job = nil diff --git a/arcgis-ios-sdk-samples/Layers/Identify raster cell/IdentifyRasterCell.storyboard b/arcgis-ios-sdk-samples/Layers/Identify raster cell/IdentifyRasterCell.storyboard index 084576d05..1dcf879a4 100644 --- a/arcgis-ios-sdk-samples/Layers/Identify raster cell/IdentifyRasterCell.storyboard +++ b/arcgis-ios-sdk-samples/Layers/Identify raster cell/IdentifyRasterCell.storyboard @@ -1,9 +1,9 @@ - + - + @@ -43,13 +43,13 @@ diff --git a/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/ApplyScheduledUpdatesToPreplannedMapAreaViewController.swift b/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/ApplyScheduledUpdatesToPreplannedMapAreaViewController.swift index 943ba1902..08a8d0b20 100644 --- a/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/ApplyScheduledUpdatesToPreplannedMapAreaViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Apply scheduled updates to preplanned map area/ApplyScheduledUpdatesToPreplannedMapAreaViewController.swift @@ -97,16 +97,11 @@ class ApplyScheduledUpdatesToPreplannedMapAreaViewController: UIViewController { let alertController: UIAlertController if updatesInfo.downloadAvailability == .available { let downloadSize = updatesInfo.scheduledUpdatesDownloadSize - let downloadSizeString: String - if #available(iOS 13.0, *) { - let measurement = Measurement( - value: Double(downloadSize), - unit: UnitInformationStorage.bytes - ) - downloadSizeString = ByteCountFormatter.string(from: measurement, countStyle: .file) - } else { - downloadSizeString = ByteCountFormatter.string(fromByteCount: Int64(downloadSize), countStyle: .file) - } + let measurement = Measurement( + value: Double(downloadSize), + unit: UnitInformationStorage.bytes + ) + let downloadSizeString = ByteCountFormatter.string(from: measurement, countStyle: .file) alertController = UIAlertController( title: "Scheduled Updates Available", message: "A \(downloadSizeString) update is available. Would you like to apply it?", diff --git a/arcgis-ios-sdk-samples/Maps/Create and save a map/CreateSaveMapViewController.swift b/arcgis-ios-sdk-samples/Maps/Create and save a map/CreateSaveMapViewController.swift index 6d698c0a7..5d5679017 100644 --- a/arcgis-ios-sdk-samples/Maps/Create and save a map/CreateSaveMapViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Create and save a map/CreateSaveMapViewController.swift @@ -120,7 +120,7 @@ class CreateSaveMapViewController: UIViewController, CreateOptionsViewController // MARK: - SaveAsViewControllerDelegate func saveAsViewController(_ saveAsViewController: SaveAsViewController, didInitiateSaveWithTitle title: String, tags: [String], itemDescription: String) { - SVProgressHUD.show(withStatus: "Saving") + UIApplication.shared.showProgressHUD(message: "Saving") // Set the initial viewpoint from map view. mapView.map?.initialViewpoint = mapView.currentViewpoint(with: AGSViewpointType.centerAndScale) @@ -136,7 +136,7 @@ class CreateSaveMapViewController: UIViewController, CreateOptionsViewController self.mapView.map?.save(as: title, portal: self.portal!, tags: tags, folder: nil, itemDescription: itemDescription, thumbnail: croppedImage, forceSaveToSupportedVersion: true) { [weak self] (error) in // Dismiss progress hud. - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { saveAsViewController.presentAlert(error: error) } else { diff --git a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/SimulatedNMEADataSource.swift b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/SimulatedNMEADataSource.swift index 410eb09a5..7ec694d42 100644 --- a/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/SimulatedNMEADataSource.swift +++ b/arcgis-ios-sdk-samples/Maps/Display device location with NMEA data sources/SimulatedNMEADataSource.swift @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +import Foundation + protocol SimulatedNMEADataSourceDelegate: AnyObject { /// A mock delegate method to receive NMEA data updates. /// Replace it with the real one to receive NMEA sentences from a GPS dongle. diff --git a/arcgis-ios-sdk-samples/Maps/Generate offline map (overrides)/GenerateOfflineMapOverridesViewController.swift b/arcgis-ios-sdk-samples/Maps/Generate offline map (overrides)/GenerateOfflineMapOverridesViewController.swift index a589baf2f..b7ca38d1f 100644 --- a/arcgis-ios-sdk-samples/Maps/Generate offline map (overrides)/GenerateOfflineMapOverridesViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Generate offline map (overrides)/GenerateOfflineMapOverridesViewController.swift @@ -223,7 +223,7 @@ class GenerateOfflineMapOverridesViewController: UIViewController, AGSAuthentica extentView.isHidden = true // show progress hud - SVProgressHUD.show(withStatus: "Getting default parameters") + UIApplication.shared.showProgressHUD(message: "Getting default parameters") // get the area outlined by the extent view let areaOfInterest = extentViewFrameToEnvelope() @@ -231,7 +231,7 @@ class GenerateOfflineMapOverridesViewController: UIViewController, AGSAuthentica // default parameters for offline map task offlineMapTask.defaultGenerateOfflineMapParameters(withAreaOfInterest: areaOfInterest) { [weak self] (parameters: AGSGenerateOfflineMapParameters?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return diff --git a/arcgis-ios-sdk-samples/Maps/Generate offline map/GenerateOfflineMapViewController.swift b/arcgis-ios-sdk-samples/Maps/Generate offline map/GenerateOfflineMapViewController.swift index fcb5ed14d..00c9185ae 100644 --- a/arcgis-ios-sdk-samples/Maps/Generate offline map/GenerateOfflineMapViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Generate offline map/GenerateOfflineMapViewController.swift @@ -170,7 +170,7 @@ class GenerateOfflineMapViewController: UIViewController, AGSAuthenticationManag extentView.isHidden = true // show progress hud - SVProgressHUD.show(withStatus: "Getting default parameters") + UIApplication.shared.showProgressHUD(message: "Getting default parameters") // get the area outlined by the extent view let areaOfInterest = extentViewFrameToEnvelope() @@ -178,7 +178,7 @@ class GenerateOfflineMapViewController: UIViewController, AGSAuthenticationManag // default parameters for offline map task offlineMapTask?.defaultGenerateOfflineMapParameters(withAreaOfInterest: areaOfInterest) { [weak self] (parameters: AGSGenerateOfflineMapParameters?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let parameters = parameters, let self = self else { diff --git a/arcgis-ios-sdk-samples/Maps/Identify layers/IdentifyLayersViewController.swift b/arcgis-ios-sdk-samples/Maps/Identify layers/IdentifyLayersViewController.swift index 93d5c1a35..9ccbe7d29 100644 --- a/arcgis-ios-sdk-samples/Maps/Identify layers/IdentifyLayersViewController.swift +++ b/arcgis-ios-sdk-samples/Maps/Identify layers/IdentifyLayersViewController.swift @@ -69,11 +69,11 @@ class IdentifyLayersViewController: UIViewController, AGSGeoViewTouchDelegate { private func identifyLayers(_ screen: CGPoint) { // Show progress hud. - SVProgressHUD.show(withStatus: "Identifying") + UIApplication.shared.showProgressHUD(message: "Identifying") self.mapView.identifyLayers(atScreenPoint: screen, tolerance: 12, returnPopupsOnly: false, maximumResultsPerLayer: 10) { (results: [AGSIdentifyLayerResult]?, error: Error?) in // Dismiss progress hud. - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() if let error = error { self.presentAlert(error: error) diff --git a/arcgis-ios-sdk-samples/Route and directions/Find service area interactive/FindServiceAreaInteractiveViewController.swift b/arcgis-ios-sdk-samples/Route and directions/Find service area interactive/FindServiceAreaInteractiveViewController.swift index 0d689042c..e5f9bff8d 100644 --- a/arcgis-ios-sdk-samples/Route and directions/Find service area interactive/FindServiceAreaInteractiveViewController.swift +++ b/arcgis-ios-sdk-samples/Route and directions/Find service area interactive/FindServiceAreaInteractiveViewController.swift @@ -149,12 +149,12 @@ class FindServiceAreaInteractiveViewController: UIViewController, AGSGeoViewTouc serviceAreaParameters.geometryAtOverlap = .dissolve // show progress hud - SVProgressHUD.show(withStatus: "Loading") + UIApplication.shared.showProgressHUD(message: "Loading") // solve for service area serviceAreaTask.solveServiceArea(with: serviceAreaParameters) { [weak self] (result: AGSServiceAreaResult?, error: Error?) in // dismiss progress hud - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return diff --git a/arcgis-ios-sdk-samples/Route and directions/Navigate route with rerouting/NavigateRouteWithReroutingViewController.swift b/arcgis-ios-sdk-samples/Route and directions/Navigate route with rerouting/NavigateRouteWithReroutingViewController.swift index fd0fe45aa..56f434047 100644 --- a/arcgis-ios-sdk-samples/Route and directions/Navigate route with rerouting/NavigateRouteWithReroutingViewController.swift +++ b/arcgis-ios-sdk-samples/Route and directions/Navigate route with rerouting/NavigateRouteWithReroutingViewController.swift @@ -44,7 +44,7 @@ class NavigateRouteWithReroutingViewController: UIViewController { /// The route tracker for navigation. Use delegate methods to update tracking status. var routeTracker: AGSRouteTracker! /// The parameters of the route tracker. - var routeParameters: AGSRouteParameters? + var routeParameters: AGSRouteParameters! /// A list to keep track of directions solved by the route task. var directionManeuvers: [AGSDirectionManeuver] = [] /// The graphic (with a dashed line symbol) to represent the route ahead. @@ -168,7 +168,8 @@ class NavigateRouteWithReroutingViewController: UIViewController { func makeRouteTracker(result: AGSRouteResult) -> AGSRouteTracker { let tracker = AGSRouteTracker(routeResult: result, routeIndex: 0, skipCoincidentStops: true)! if routeTask.routeTaskInfo().supportsRerouting { - tracker.enableRerouting(with: routeTask, routeParameters: routeParameters!, strategy: .toNextWaypoint, visitFirstStopOnStart: false) { error in + let reroutingParameters = AGSReroutingParameters(routeTask: routeTask, routeParameters: routeParameters)! + tracker.enableRerouting(with: reroutingParameters) { error in if let error = error { self.presentAlert(error: error) } diff --git a/arcgis-ios-sdk-samples/Route and directions/Route around barriers/RouteAroundBarriersViewController.swift b/arcgis-ios-sdk-samples/Route and directions/Route around barriers/RouteAroundBarriersViewController.swift index 181744b5f..6d7a478ca 100644 --- a/arcgis-ios-sdk-samples/Route and directions/Route around barriers/RouteAroundBarriersViewController.swift +++ b/arcgis-ios-sdk-samples/Route and directions/Route around barriers/RouteAroundBarriersViewController.swift @@ -121,10 +121,10 @@ class RouteAroundBarriersViewController: UIViewController, AGSGeoViewTouchDelega self.routeParameters.clearPolygonBarriers() self.routeParameters.setPolygonBarriers(barriers) - SVProgressHUD.show(withStatus: "Routing") + UIApplication.shared.showProgressHUD(message: "Routing") self.routeTask.solveRoute(with: self.routeParameters) { [weak self] (routeResult: AGSRouteResult?, error: Error?) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return diff --git a/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.md b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.md new file mode 100644 index 000000000..049de220c --- /dev/null +++ b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.md @@ -0,0 +1,40 @@ +# Show labels on layer in 3D + +Display custom labels in a 3D scene. + +![Show labels on layer in 3D](show-labels-on-layer-3d.png) + +## Use case + +Labeling features is useful to visually display information or attributes on a scene. For example, city officials or maintenance crews may want to show installation dates of features of a gas network. + +## How to use the sample + +Pan and zoom to explore the scene. Notice the labels showing installation dates of features in the 3D gas network. + +## How it works + +1. Create an `AGSScene` using a URL. +2. Assign the scene to an `AGSSceneView` and load it. +3. After loading is complete, obtain the `AGSFeatureLayer` from the scene's `operationalLayers` property. +4. Set the feature layer's `labelsEnabled` property to `true`. +5. Create an `AGSTextSymbol` to use for displaying the label text. +6. Create an `AGSLabelDefinition` using an `AGSArcadeLabelExpression`. +7. Add the definition to the feature layer's `labelDefinitions` array. + +## Relevant API + +* AGSArcadeLabelExpression +* AGSFeatureLayer +* AGSLabelDefinition +* AGSScene +* AGSSceneView +* AGSTextSymbol + +## About the data + +This sample shows a [New York City infrastructure](https://www.arcgis.com/home/item.html?id=850dfee7d30f4d9da0ebca34a533c169) scene hosted on ArcGIS Online. + +## Tags + +3D, arcade, attribute, buildings, label, model, scene, symbol, text, URL, visualization diff --git a/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.metadata.json b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.metadata.json new file mode 100644 index 000000000..db3dbaca4 --- /dev/null +++ b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/README.metadata.json @@ -0,0 +1,40 @@ +{ + "category": "Scenes", + "description": "Display custom labels in a 3D scene.", + "ignore": false, + "images": [ + "show-labels-on-layer-3d.png" + ], + "keywords": [ + "3D", + "URL", + "arcade", + "attribute", + "buildings", + "label", + "model", + "scene", + "symbol", + "text", + "visualization", + "AGSArcadeLabelExpression", + "AGSFeatureLayer", + "AGSLabelDefinition", + "AGSScene", + "AGSSceneView", + "AGSTextSymbol" + ], + "redirect_from": [], + "relevant_apis": [ + "AGSArcadeLabelExpression", + "AGSFeatureLayer", + "AGSLabelDefinition", + "AGSScene", + "AGSSceneView", + "AGSTextSymbol" + ], + "snippets": [ + "ShowLabelsOnLayer3DViewController.swift" + ], + "title": "Show labels on layer in 3D" +} diff --git a/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3D.storyboard b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3D.storyboard new file mode 100644 index 000000000..55c8eedbb --- /dev/null +++ b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3D.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3DViewController.swift b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3DViewController.swift new file mode 100644 index 000000000..227af152f --- /dev/null +++ b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/ShowLabelsOnLayer3DViewController.swift @@ -0,0 +1,80 @@ +// 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 ShowLabelsOnLayer3DViewController: UIViewController { + @IBOutlet var sceneView: AGSSceneView! { + didSet { + // Set the scene to the scene view. + sceneView.scene = makeScene() + } + } + + func makeScene() -> AGSScene { + let scene = AGSScene( + item: AGSPortalItem( + portal: AGSPortal.arcGISOnline(withLoginRequired: false), + itemID: "850dfee7d30f4d9da0ebca34a533c169" + ) + ) + // Load the scene. + scene.load { [weak self] error in + guard let self = self else { return } + // Get the feature layer. + if let operationalLayers = scene.operationalLayers as? [AGSGroupLayer], + let groupLayer = operationalLayers.first(where: { $0.name == "Gas" }), + let layers = groupLayer.layers as? [AGSLayer], + let gasFeatureLayer = layers.first(where: { $0.name == "Gas Main" }) as? AGSFeatureLayer { + let labelDefinition = self.makeLabelDefinition() + // Enable labels on the feature layer. + gasFeatureLayer.labelsEnabled = true + // Set the layer's label definitions. + gasFeatureLayer.labelDefinitions.setArray([labelDefinition]) + } else if let error = error { + self.presentAlert(error: error) + } + } + return scene + } + + func makeLabelDefinition() -> AGSLabelDefinition { + // Make and stylize the text symbol. + let textSymbol = AGSTextSymbol() + textSymbol.color = .orange + textSymbol.haloColor = .white + textSymbol.haloWidth = 2 + textSymbol.size = 16 + + // Create and return a label definition using the text symbol. + let labelDefinition = AGSLabelDefinition() + // Set an arcade expression to provide better formatting. + labelDefinition.expression = AGSArcadeLabelExpression(arcadeString: "Text($feature.INSTALLATIONDATE, `DD MMM YY`)") + labelDefinition.placement = .lineAboveAlong + labelDefinition.useCodedValues = true + labelDefinition.textSymbol = textSymbol + + return labelDefinition + } + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + + // Add the source code button item to the right of navigation bar. + (navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["ShowLabelsOnLayer3DViewController"] + } +} diff --git a/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/show-labels-on-layer-3d.png b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/show-labels-on-layer-3d.png new file mode 100644 index 000000000..ecb074ab1 Binary files /dev/null and b/arcgis-ios-sdk-samples/Scenes/Show labels on layer in 3D/show-labels-on-layer-3d.png differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/DemoTouchManager/DemoTouchManager.swift b/arcgis-ios-sdk-samples/Shared resources/Libraries/DemoTouchManager/DemoTouchManager.swift index 544cff8af..2f7c53706 100755 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/DemoTouchManager/DemoTouchManager.swift +++ b/arcgis-ios-sdk-samples/Shared resources/Libraries/DemoTouchManager/DemoTouchManager.swift @@ -237,7 +237,7 @@ class DemoTouchManager { if let window = view.window { window.bringSubviewToFront(view) } else { - UIApplication.shared.keyWindow?.addSubview(view) + UIApplication.shared.windows.first(where: \.isKeyWindow)?.addSubview(view) } view.updateTouches(touches) } diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h deleted file mode 100755 index b624dd0b3..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// SVIndefiniteAnimatedView.h -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved. -// - -#import - -@interface SVIndefiniteAnimatedView : UIView - -@property (nonatomic, assign) CGFloat strokeThickness; -@property (nonatomic, assign) CGFloat radius; -@property (nonatomic, strong) UIColor *strokeColor; - -@end - diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m deleted file mode 100755 index 09a38d0b0..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m +++ /dev/null @@ -1,137 +0,0 @@ -// -// SVIndefiniteAnimatedView.m -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved. -// - -#import "SVIndefiniteAnimatedView.h" -#import "SVProgressHUD.h" - -@interface SVIndefiniteAnimatedView () - -@property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer; - -@end - -@implementation SVIndefiniteAnimatedView - -- (void)willMoveToSuperview:(UIView*)newSuperview { - if (newSuperview) { - [self layoutAnimatedLayer]; - } else { - [_indefiniteAnimatedLayer removeFromSuperlayer]; - _indefiniteAnimatedLayer = nil; - } -} - -- (void)layoutAnimatedLayer { - CALayer *layer = self.indefiniteAnimatedLayer; - [self.layer addSublayer:layer]; - - CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); - CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); - layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); -} - -- (CAShapeLayer*)indefiniteAnimatedLayer { - if(!_indefiniteAnimatedLayer) { - CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); - UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (M_PI/2+M_PI*5) clockwise:YES]; - - _indefiniteAnimatedLayer = [CAShapeLayer layer]; - _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; - _indefiniteAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); - _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; - _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; - _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; - _indefiniteAnimatedLayer.lineCap = kCALineCapRound; - _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; - _indefiniteAnimatedLayer.path = smoothedPath.CGPath; - - CALayer *maskLayer = [CALayer layer]; - - NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; - NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; - NSBundle *imageBundle = [NSBundle bundleWithURL:url]; - - NSString *path = [imageBundle pathForResource:@"angle-mask" ofType:@"png"]; - - maskLayer.contents = (__bridge id)[[UIImage imageWithContentsOfFile:path] CGImage]; - maskLayer.frame = _indefiniteAnimatedLayer.bounds; - _indefiniteAnimatedLayer.mask = maskLayer; - - NSTimeInterval animationDuration = 1; - CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; - - CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; - animation.fromValue = (id) 0; - animation.toValue = @(M_PI*2); - animation.duration = animationDuration; - animation.timingFunction = linearCurve; - animation.removedOnCompletion = NO; - animation.repeatCount = INFINITY; - animation.fillMode = kCAFillModeForwards; - animation.autoreverses = NO; - [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; - - CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; - animationGroup.duration = animationDuration; - animationGroup.repeatCount = INFINITY; - animationGroup.removedOnCompletion = NO; - animationGroup.timingFunction = linearCurve; - - CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; - strokeStartAnimation.fromValue = @0.015; - strokeStartAnimation.toValue = @0.515; - - CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; - strokeEndAnimation.fromValue = @0.485; - strokeEndAnimation.toValue = @0.985; - - animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; - [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; - - } - return _indefiniteAnimatedLayer; -} - -- (void)setFrame:(CGRect)frame { - if(!CGRectEqualToRect(frame, super.frame)) { - [super setFrame:frame]; - - if(self.superview) { - [self layoutAnimatedLayer]; - } - } - -} - -- (void)setRadius:(CGFloat)radius { - if(radius != _radius) { - _radius = radius; - - [_indefiniteAnimatedLayer removeFromSuperlayer]; - _indefiniteAnimatedLayer = nil; - - if(self.superview) { - [self layoutAnimatedLayer]; - } - } -} - -- (void)setStrokeColor:(UIColor*)strokeColor { - _strokeColor = strokeColor; - _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; -} - -- (void)setStrokeThickness:(CGFloat)strokeThickness { - _strokeThickness = strokeThickness; - _indefiniteAnimatedLayer.lineWidth = _strokeThickness; -} - -- (CGSize)sizeThatFits:(CGSize)size { - return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); -} - -@end diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.h b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.h deleted file mode 100755 index 6de23b432..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// SVProgressAnimatedView.h -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2017-2018 Tobias Tiemerding. All rights reserved. -// - -#import - -@interface SVProgressAnimatedView : UIView - -@property (nonatomic, assign) CGFloat radius; -@property (nonatomic, assign) CGFloat strokeThickness; -@property (nonatomic, strong) UIColor *strokeColor; -@property (nonatomic, assign) CGFloat strokeEnd; - -@end diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.m b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.m deleted file mode 100755 index a347c85d2..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressAnimatedView.m +++ /dev/null @@ -1,96 +0,0 @@ -// -// SVProgressAnimatedView.m -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2017-2018 Tobias Tiemerding. All rights reserved. -// - -#import "SVProgressAnimatedView.h" - -@interface SVProgressAnimatedView () - -@property (nonatomic, strong) CAShapeLayer *ringAnimatedLayer; - -@end - -@implementation SVProgressAnimatedView - -- (void)willMoveToSuperview:(UIView*)newSuperview { - if (newSuperview) { - [self layoutAnimatedLayer]; - } else { - [_ringAnimatedLayer removeFromSuperlayer]; - _ringAnimatedLayer = nil; - } -} - -- (void)layoutAnimatedLayer { - CALayer *layer = self.ringAnimatedLayer; - [self.layer addSublayer:layer]; - - CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); - CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); - layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); -} - -- (CAShapeLayer*)ringAnimatedLayer { - if(!_ringAnimatedLayer) { - CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); - UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat)-M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES]; - - _ringAnimatedLayer = [CAShapeLayer layer]; - _ringAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; - _ringAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); - _ringAnimatedLayer.fillColor = [UIColor clearColor].CGColor; - _ringAnimatedLayer.strokeColor = self.strokeColor.CGColor; - _ringAnimatedLayer.lineWidth = self.strokeThickness; - _ringAnimatedLayer.lineCap = kCALineCapRound; - _ringAnimatedLayer.lineJoin = kCALineJoinBevel; - _ringAnimatedLayer.path = smoothedPath.CGPath; - } - return _ringAnimatedLayer; -} - -- (void)setFrame:(CGRect)frame { - if(!CGRectEqualToRect(frame, super.frame)) { - [super setFrame:frame]; - - if(self.superview) { - [self layoutAnimatedLayer]; - } - } -} - -- (void)setRadius:(CGFloat)radius { - if(radius != _radius) { - _radius = radius; - - [_ringAnimatedLayer removeFromSuperlayer]; - _ringAnimatedLayer = nil; - - if(self.superview) { - [self layoutAnimatedLayer]; - } - } -} - -- (void)setStrokeColor:(UIColor*)strokeColor { - _strokeColor = strokeColor; - _ringAnimatedLayer.strokeColor = strokeColor.CGColor; -} - -- (void)setStrokeThickness:(CGFloat)strokeThickness { - _strokeThickness = strokeThickness; - _ringAnimatedLayer.lineWidth = _strokeThickness; -} - -- (void)setStrokeEnd:(CGFloat)strokeEnd { - _strokeEnd = strokeEnd; - _ringAnimatedLayer.strokeEnd = _strokeEnd; -} - -- (CGSize)sizeThatFits:(CGSize)size { - return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); -} - -@end diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch deleted file mode 100755 index 2fff99788..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -// -// Prefix header for all source files of the 'SVProgressHUD' target in the 'SVProgressHUD' project -// - -#ifdef __OBJC__ - #import -#endif diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png deleted file mode 100755 index 0150a03f5..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png deleted file mode 100755 index 9a302b680..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png deleted file mode 100755 index d07f3ce67..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png deleted file mode 100755 index a57c8e446..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png deleted file mode 100755 index aaf679854..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png deleted file mode 100755 index c92518f85..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png deleted file mode 100755 index a3a1f75c2..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png deleted file mode 100755 index 1b333e7b8..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png deleted file mode 100755 index d56aa0c22..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png deleted file mode 100755 index 44769d028..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png deleted file mode 100755 index a9d16532f..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png deleted file mode 100755 index 42bad9be6..000000000 Binary files a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png and /dev/null differ diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.h b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.h deleted file mode 100755 index 6aa935c0b..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.h +++ /dev/null @@ -1,147 +0,0 @@ -// -// SVProgressHUD.h -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2011-2018 Sam Vermette and contributors. All rights reserved. -// - -#import -#import - -extern NSString * _Nonnull const SVProgressHUDDidReceiveTouchEventNotification; -extern NSString * _Nonnull const SVProgressHUDDidTouchDownInsideNotification; -extern NSString * _Nonnull const SVProgressHUDWillDisappearNotification; -extern NSString * _Nonnull const SVProgressHUDDidDisappearNotification; -extern NSString * _Nonnull const SVProgressHUDWillAppearNotification; -extern NSString * _Nonnull const SVProgressHUDDidAppearNotification; - -extern NSString * _Nonnull const SVProgressHUDStatusUserInfoKey; - -typedef NS_ENUM(NSInteger, SVProgressHUDStyle) { - SVProgressHUDStyleLight, // default style, white HUD with black text, HUD background will be blurred - SVProgressHUDStyleDark, // black HUD and white text, HUD background will be blurred - SVProgressHUDStyleCustom // uses the fore- and background color properties -}; - -typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) { - SVProgressHUDMaskTypeNone = 1, // default mask type, allow user interactions while HUD is displayed - SVProgressHUDMaskTypeClear, // don't allow user interactions with background objects - SVProgressHUDMaskTypeBlack, // don't allow user interactions with background objects and dim the UI in the back of the HUD (as seen in iOS 7 and above) - SVProgressHUDMaskTypeGradient, // don't allow user interactions with background objects and dim the UI with a a-la UIAlertView background gradient (as seen in iOS 6) - SVProgressHUDMaskTypeCustom // don't allow user interactions with background objects and dim the UI in the back of the HUD with a custom color -}; - -typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) { - SVProgressHUDAnimationTypeFlat, // default animation type, custom flat animation (indefinite animated ring) - SVProgressHUDAnimationTypeNative // iOS native UIActivityIndicatorView -}; - -typedef void (^SVProgressHUDShowCompletion)(void); -typedef void (^SVProgressHUDDismissCompletion)(void); - -@interface SVProgressHUD : UIView - -#pragma mark - Customization - -@property (assign, nonatomic) SVProgressHUDStyle defaultStyle UI_APPEARANCE_SELECTOR; // default is SVProgressHUDStyleLight -@property (assign, nonatomic) SVProgressHUDMaskType defaultMaskType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDMaskTypeNone -@property (assign, nonatomic) SVProgressHUDAnimationType defaultAnimationType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDAnimationTypeFlat -@property (strong, nonatomic, nullable) UIView *containerView; // if nil then use default window level -@property (assign, nonatomic) CGSize minimumSize UI_APPEARANCE_SELECTOR; // default is CGSizeZero, can be used to avoid resizing for a larger message -@property (assign, nonatomic) CGFloat ringThickness UI_APPEARANCE_SELECTOR; // default is 2 pt -@property (assign, nonatomic) CGFloat ringRadius UI_APPEARANCE_SELECTOR; // default is 18 pt -@property (assign, nonatomic) CGFloat ringNoTextRadius UI_APPEARANCE_SELECTOR; // default is 24 pt -@property (assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // default is 14 pt -@property (strong, nonatomic, nonnull) UIFont *font UI_APPEARANCE_SELECTOR; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] -@property (strong, nonatomic, nonnull) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor whiteColor] -@property (strong, nonatomic, nonnull) UIColor *foregroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor blackColor] -@property (strong, nonatomic, nonnull) UIColor *backgroundLayerColor UI_APPEARANCE_SELECTOR;// default is [UIColor colorWithWhite:0 alpha:0.4] -@property (assign, nonatomic) CGSize imageViewSize UI_APPEARANCE_SELECTOR; // default is 28x28 pt -@property (assign, nonatomic) BOOL shouldTintImages UI_APPEARANCE_SELECTOR; // default is YES -@property (strong, nonatomic, nonnull) UIImage *infoImage UI_APPEARANCE_SELECTOR; // default is the bundled info image provided by Freepik -@property (strong, nonatomic, nonnull) UIImage *successImage UI_APPEARANCE_SELECTOR; // default is the bundled success image provided by Freepik -@property (strong, nonatomic, nonnull) UIImage *errorImage UI_APPEARANCE_SELECTOR; // default is the bundled error image provided by Freepik -@property (strong, nonatomic, nonnull) UIView *viewForExtension UI_APPEARANCE_SELECTOR; // default is nil, only used if #define SV_APP_EXTENSIONS is set -@property (assign, nonatomic) NSTimeInterval graceTimeInterval; // default is 0 seconds -@property (assign, nonatomic) NSTimeInterval minimumDismissTimeInterval; // default is 5.0 seconds -@property (assign, nonatomic) NSTimeInterval maximumDismissTimeInterval; // default is CGFLOAT_MAX - -@property (assign, nonatomic) UIOffset offsetFromCenter UI_APPEARANCE_SELECTOR; // default is 0, 0 - -@property (assign, nonatomic) NSTimeInterval fadeInAnimationDuration UI_APPEARANCE_SELECTOR; // default is 0.15 -@property (assign, nonatomic) NSTimeInterval fadeOutAnimationDuration UI_APPEARANCE_SELECTOR; // default is 0.15 - -@property (assign, nonatomic) UIWindowLevel maxSupportedWindowLevel; // default is UIWindowLevelNormal - -@property (assign, nonatomic) BOOL hapticsEnabled; // default is NO - -+ (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight -+ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone -+ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat -+ (void)setContainerView:(nullable UIView*)containerView; // default is window level -+ (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing for a larger message -+ (void)setRingThickness:(CGFloat)ringThickness; // default is 2 pt -+ (void)setRingRadius:(CGFloat)radius; // default is 18 pt -+ (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt -+ (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt -+ (void)setBorderColor:(nonnull UIColor*)color; // default is nil -+ (void)setBorderWidth:(CGFloat)width; // default is 0 -+ (void)setFont:(nonnull UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] -+ (void)setForegroundColor:(nonnull UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom -+ (void)setBackgroundColor:(nonnull UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom -+ (void)setBackgroundLayerColor:(nonnull UIColor*)color; // default is [UIColor colorWithWhite:0 alpha:0.5], only used for SVProgressHUDMaskTypeCustom -+ (void)setImageViewSize:(CGSize)size; // default is 28x28 pt -+ (void)setShouldTintImages:(BOOL)shouldTintImages; // default is YES -+ (void)setInfoImage:(nonnull UIImage*)image; // default is the bundled info image provided by Freepik -+ (void)setSuccessImage:(nonnull UIImage*)image; // default is the bundled success image provided by Freepik -+ (void)setErrorImage:(nonnull UIImage*)image; // default is the bundled error image provided by Freepik -+ (void)setViewForExtension:(nonnull UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set -+ (void)setGraceTimeInterval:(NSTimeInterval)interval; // default is 0 seconds -+ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds -+ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval; // default is infinite -+ (void)setFadeInAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds -+ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds -+ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel; // default is UIWindowLevelNormal -+ (void)setHapticsEnabled:(BOOL)hapticsEnabled; // default is NO - -#pragma mark - Show Methods - -+ (void)show; -+ (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead."))); -+ (void)showWithStatus:(nullable NSString*)status; -+ (void)showWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showWithStatus: and setDefaultMaskType: instead."))); - -+ (void)showProgress:(float)progress; -+ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress: and setDefaultMaskType: instead."))); -+ (void)showProgress:(float)progress status:(nullable NSString*)status; -+ (void)showProgress:(float)progress status:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress:status: and setDefaultMaskType: instead."))); - -+ (void)setStatus:(nullable NSString*)status; // change the HUD loading status while it's showing - -// stops the activity indicator, shows a glyph + status, and dismisses the HUD a little bit later -+ (void)showInfoWithStatus:(nullable NSString*)status; -+ (void)showInfoWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showInfoWithStatus: and setDefaultMaskType: instead."))); -+ (void)showSuccessWithStatus:(nullable NSString*)status; -+ (void)showSuccessWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showSuccessWithStatus: and setDefaultMaskType: instead."))); -+ (void)showErrorWithStatus:(nullable NSString*)status; -+ (void)showErrorWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showErrorWithStatus: and setDefaultMaskType: instead."))); - -// shows a image + status, use white PNGs with the imageViewSize (default is 28x28 pt) -+ (void)showImage:(nonnull UIImage*)image status:(nullable NSString*)status; -+ (void)showImage:(nonnull UIImage*)image status:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showImage:status: and setDefaultMaskType: instead."))); - -+ (void)setOffsetFromCenter:(UIOffset)offset; -+ (void)resetOffsetFromCenter; - -+ (void)popActivity; // decrease activity count, if activity count == 0 the HUD is dismissed -+ (void)dismiss; -+ (void)dismissWithCompletion:(nullable SVProgressHUDDismissCompletion)completion; -+ (void)dismissWithDelay:(NSTimeInterval)delay; -+ (void)dismissWithDelay:(NSTimeInterval)delay completion:(nullable SVProgressHUDDismissCompletion)completion; - -+ (BOOL)isVisible; - -+ (NSTimeInterval)displayDurationForString:(nullable NSString*)string; - -@end - diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.m b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.m deleted file mode 100755 index 2b6699209..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVProgressHUD.m +++ /dev/null @@ -1,1509 +0,0 @@ -// -// SVProgressHUD.h -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2011-2018 Sam Vermette and contributors. All rights reserved. -// - -#if !__has_feature(objc_arc) -#error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag -#endif - -#import "SVProgressHUD.h" -#import "SVIndefiniteAnimatedView.h" -#import "SVProgressAnimatedView.h" -#import "SVRadialGradientLayer.h" - -NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification"; -NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification"; -NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification"; -NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification"; -NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification"; -NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification"; - -NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey"; - -static const CGFloat SVProgressHUDParallaxDepthPoints = 10.0f; -static const CGFloat SVProgressHUDUndefinedProgress = -1; -static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15f; -static const CGFloat SVProgressHUDVerticalSpacing = 12.0f; -static const CGFloat SVProgressHUDHorizontalSpacing = 12.0f; -static const CGFloat SVProgressHUDLabelSpacing = 8.0f; - - -@interface SVProgressHUD () - -@property (nonatomic, strong) NSTimer *graceTimer; -@property (nonatomic, strong) NSTimer *fadeOutTimer; - -@property (nonatomic, strong) UIControl *controlView; -@property (nonatomic, strong) UIView *backgroundView; -@property (nonatomic, strong) SVRadialGradientLayer *backgroundRadialGradientLayer; -@property (nonatomic, strong) UIVisualEffectView *hudView; -@property (nonatomic, strong) UILabel *statusLabel; -@property (nonatomic, strong) UIImageView *imageView; - -@property (nonatomic, strong) UIView *indefiniteAnimatedView; -@property (nonatomic, strong) SVProgressAnimatedView *ringView; -@property (nonatomic, strong) SVProgressAnimatedView *backgroundRingView; - -@property (nonatomic, readwrite) CGFloat progress; -@property (nonatomic, readwrite) NSUInteger activityCount; - -@property (nonatomic, readonly) CGFloat visibleKeyboardHeight; -@property (nonatomic, readonly) UIWindow *frontWindow; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 -@property (nonatomic, strong) UINotificationFeedbackGenerator *hapticGenerator NS_AVAILABLE_IOS(10_0); -#endif - -@end - -@implementation SVProgressHUD { - BOOL _isInitializing; -} - -+ (SVProgressHUD*)sharedView { - static dispatch_once_t once; - - static SVProgressHUD *sharedView; -#if !defined(SV_APP_EXTENSIONS) - dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[[UIApplication sharedApplication] delegate] window].bounds]; }); -#else - dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; }); -#endif - return sharedView; -} - - -#pragma mark - Setters - -+ (void)setStatus:(NSString*)status { - [[self sharedView] setStatus:status]; -} - -+ (void)setDefaultStyle:(SVProgressHUDStyle)style { - [self sharedView].defaultStyle = style; -} - -+ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { - [self sharedView].defaultMaskType = maskType; -} - -+ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type { - [self sharedView].defaultAnimationType = type; -} - -+ (void)setContainerView:(nullable UIView*)containerView { - [self sharedView].containerView = containerView; -} - -+ (void)setMinimumSize:(CGSize)minimumSize { - [self sharedView].minimumSize = minimumSize; -} - -+ (void)setRingThickness:(CGFloat)ringThickness { - [self sharedView].ringThickness = ringThickness; -} - -+ (void)setRingRadius:(CGFloat)radius { - [self sharedView].ringRadius = radius; -} - -+ (void)setRingNoTextRadius:(CGFloat)radius { - [self sharedView].ringNoTextRadius = radius; -} - -+ (void)setCornerRadius:(CGFloat)cornerRadius { - [self sharedView].cornerRadius = cornerRadius; -} - -+ (void)setBorderColor:(nonnull UIColor*)color { - [self sharedView].hudView.layer.borderColor = color.CGColor; -} - -+ (void)setBorderWidth:(CGFloat)width { - [self sharedView].hudView.layer.borderWidth = width; -} - -+ (void)setFont:(UIFont*)font { - [self sharedView].font = font; -} - -+ (void)setForegroundColor:(UIColor*)color { - [self sharedView].foregroundColor = color; - [self setDefaultStyle:SVProgressHUDStyleCustom]; -} - -+ (void)setBackgroundColor:(UIColor*)color { - [self sharedView].backgroundColor = color; - [self setDefaultStyle:SVProgressHUDStyleCustom]; -} - -+ (void)setBackgroundLayerColor:(UIColor*)color { - [self sharedView].backgroundLayerColor = color; -} - -+ (void)setImageViewSize:(CGSize)size { - [self sharedView].imageViewSize = size; -} - -+ (void)setShouldTintImages:(BOOL)shouldTintImages { - [self sharedView].shouldTintImages = shouldTintImages; -} - -+ (void)setInfoImage:(UIImage*)image { - [self sharedView].infoImage = image; -} - -+ (void)setSuccessImage:(UIImage*)image { - [self sharedView].successImage = image; -} - -+ (void)setErrorImage:(UIImage*)image { - [self sharedView].errorImage = image; -} - -+ (void)setViewForExtension:(UIView*)view { - [self sharedView].viewForExtension = view; -} - -+ (void)setGraceTimeInterval:(NSTimeInterval)interval { - [self sharedView].graceTimeInterval = interval; -} - -+ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval { - [self sharedView].minimumDismissTimeInterval = interval; -} - -+ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval { - [self sharedView].maximumDismissTimeInterval = interval; -} - -+ (void)setFadeInAnimationDuration:(NSTimeInterval)duration { - [self sharedView].fadeInAnimationDuration = duration; -} - -+ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { - [self sharedView].fadeOutAnimationDuration = duration; -} - -+ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel { - [self sharedView].maxSupportedWindowLevel = windowLevel; -} - -+ (void)setHapticsEnabled:(BOOL)hapticsEnabled { - [self sharedView].hapticsEnabled = hapticsEnabled; -} - -#pragma mark - Show Methods - -+ (void)show { - [self showWithStatus:nil]; -} - -+ (void)showWithMaskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self show]; - [self setDefaultMaskType:existingMaskType]; -} - -+ (void)showWithStatus:(NSString*)status { - [self showProgress:SVProgressHUDUndefinedProgress status:status]; -} - -+ (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showWithStatus:status]; - [self setDefaultMaskType:existingMaskType]; -} - -+ (void)showProgress:(float)progress { - [self showProgress:progress status:nil]; -} - -+ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showProgress:progress]; - [self setDefaultMaskType:existingMaskType]; -} - -+ (void)showProgress:(float)progress status:(NSString*)status { - [[self sharedView] showProgress:progress status:status]; -} - -+ (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showProgress:progress status:status]; - [self setDefaultMaskType:existingMaskType]; -} - - -#pragma mark - Show, then automatically dismiss methods - -+ (void)showInfoWithStatus:(NSString*)status { - [self showImage:[self sharedView].infoImage status:status]; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10.0, *)) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeWarning]; - }); - } -#endif -} - -+ (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showInfoWithStatus:status]; - [self setDefaultMaskType:existingMaskType]; -} - -+ (void)showSuccessWithStatus:(NSString*)status { - [self showImage:[self sharedView].successImage status:status]; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10, *)) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; - }); - } -#endif -} - -+ (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showSuccessWithStatus:status]; - [self setDefaultMaskType:existingMaskType]; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10.0, *)) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; - }); - } -#endif -} - -+ (void)showErrorWithStatus:(NSString*)status { - [self showImage:[self sharedView].errorImage status:status]; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10.0, *)) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeError]; - }); - } -#endif -} - -+ (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showErrorWithStatus:status]; - [self setDefaultMaskType:existingMaskType]; - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10.0, *)) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeError]; - }); - } -#endif -} - -+ (void)showImage:(UIImage*)image status:(NSString*)status { - NSTimeInterval displayInterval = [self displayDurationForString:status]; - [[self sharedView] showImage:image status:status duration:displayInterval]; -} - -+ (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { - SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; - [self setDefaultMaskType:maskType]; - [self showImage:image status:status]; - [self setDefaultMaskType:existingMaskType]; -} - - -#pragma mark - Dismiss Methods - -+ (void)popActivity { - if([self sharedView].activityCount > 0) { - [self sharedView].activityCount--; - } - if([self sharedView].activityCount == 0) { - [[self sharedView] dismiss]; - } -} - -+ (void)dismiss { - [self dismissWithDelay:0.0 completion:nil]; -} - -+ (void)dismissWithCompletion:(SVProgressHUDDismissCompletion)completion { - [self dismissWithDelay:0.0 completion:completion]; -} - -+ (void)dismissWithDelay:(NSTimeInterval)delay { - [self dismissWithDelay:delay completion:nil]; -} - -+ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { - [[self sharedView] dismissWithDelay:delay completion:completion]; -} - - -#pragma mark - Offset - -+ (void)setOffsetFromCenter:(UIOffset)offset { - [self sharedView].offsetFromCenter = offset; -} - -+ (void)resetOffsetFromCenter { - [self setOffsetFromCenter:UIOffsetZero]; -} - - -#pragma mark - Instance Methods - -- (instancetype)initWithFrame:(CGRect)frame { - if((self = [super initWithFrame:frame])) { - _isInitializing = YES; - - self.userInteractionEnabled = NO; - self.activityCount = 0; - - self.backgroundView.alpha = 0.0f; - self.imageView.alpha = 0.0f; - self.statusLabel.alpha = 0.0f; - self.indefiniteAnimatedView.alpha = 0.0f; - self.ringView.alpha = self.backgroundRingView.alpha = 0.0f; - - - _backgroundColor = [UIColor whiteColor]; - _foregroundColor = [UIColor blackColor]; - _backgroundLayerColor = [UIColor colorWithWhite:0 alpha:0.4]; - - // Set default values - _defaultMaskType = SVProgressHUDMaskTypeNone; - _defaultStyle = SVProgressHUDStyleLight; - _defaultAnimationType = SVProgressHUDAnimationTypeFlat; - _minimumSize = CGSizeZero; - _font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; - - _imageViewSize = CGSizeMake(28.0f, 28.0f); - _shouldTintImages = YES; - - NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; - NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; - NSBundle *imageBundle = [NSBundle bundleWithURL:url]; - - _infoImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"info" ofType:@"png"]]; - _successImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"success" ofType:@"png"]]; - _errorImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"error" ofType:@"png"]]; - - _ringThickness = 2.0f; - _ringRadius = 18.0f; - _ringNoTextRadius = 24.0f; - - _cornerRadius = 14.0f; - - _graceTimeInterval = 0.0f; - _minimumDismissTimeInterval = 5.0; - _maximumDismissTimeInterval = CGFLOAT_MAX; - - _fadeInAnimationDuration = SVProgressHUDDefaultAnimationDuration; - _fadeOutAnimationDuration = SVProgressHUDDefaultAnimationDuration; - - _maxSupportedWindowLevel = UIWindowLevelNormal; - - _hapticsEnabled = NO; - - // Accessibility support - self.accessibilityIdentifier = @"SVProgressHUD"; - self.isAccessibilityElement = YES; - - _isInitializing = NO; - } - return self; -} - -- (void)updateHUDFrame { - // Check if an image or progress ring is displayed - BOOL imageUsed = (self.imageView.image) && !(self.imageView.hidden); - BOOL progressUsed = self.imageView.hidden; - - // Calculate size of string - CGRect labelRect = CGRectZero; - CGFloat labelHeight = 0.0f; - CGFloat labelWidth = 0.0f; - - if(self.statusLabel.text) { - CGSize constraintSize = CGSizeMake(200.0f, 300.0f); - labelRect = [self.statusLabel.text boundingRectWithSize:constraintSize - options:(NSStringDrawingOptions)(NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin) - attributes:@{NSFontAttributeName: self.statusLabel.font} - context:NULL]; - labelHeight = ceilf(CGRectGetHeight(labelRect)); - labelWidth = ceilf(CGRectGetWidth(labelRect)); - } - - // Calculate hud size based on content - // For the beginning use default values, these - // might get update if string is too large etc. - CGFloat hudWidth; - CGFloat hudHeight; - - CGFloat contentWidth = 0.0f; - CGFloat contentHeight = 0.0f; - - if(imageUsed || progressUsed) { - contentWidth = CGRectGetWidth(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame); - contentHeight = CGRectGetHeight(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame); - } - - // |-spacing-content-spacing-| - hudWidth = SVProgressHUDHorizontalSpacing + MAX(labelWidth, contentWidth) + SVProgressHUDHorizontalSpacing; - - // |-spacing-content-(labelSpacing-label-)spacing-| - hudHeight = SVProgressHUDVerticalSpacing + labelHeight + contentHeight + SVProgressHUDVerticalSpacing; - if(self.statusLabel.text && (imageUsed || progressUsed)){ - // Add spacing if both content and label are used - hudHeight += SVProgressHUDLabelSpacing; - } - - // Update values on subviews - self.hudView.bounds = CGRectMake(0.0f, 0.0f, MAX(self.minimumSize.width, hudWidth), MAX(self.minimumSize.height, hudHeight)); - - // Animate value update - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - // Spinner and image view - CGFloat centerY; - if(self.statusLabel.text) { - CGFloat yOffset = MAX(SVProgressHUDVerticalSpacing, (self.minimumSize.height - contentHeight - SVProgressHUDLabelSpacing - labelHeight) / 2.0f); - centerY = yOffset + contentHeight / 2.0f; - } else { - centerY = CGRectGetMidY(self.hudView.bounds); - } - self.indefiniteAnimatedView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); - if(self.progress != SVProgressHUDUndefinedProgress) { - self.backgroundRingView.center = self.ringView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); - } - self.imageView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); - - // Label - if(imageUsed || progressUsed) { - centerY = CGRectGetMaxY(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame) + SVProgressHUDLabelSpacing + labelHeight / 2.0f; - } else { - centerY = CGRectGetMidY(self.hudView.bounds); - } - self.statusLabel.frame = labelRect; - self.statusLabel.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); - - [CATransaction commit]; -} - -#if TARGET_OS_IOS -- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation { - UIInterpolatingMotionEffectType xMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis; - UIInterpolatingMotionEffectType yMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis; - [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType]; -} -#endif - -- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType { - UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType]; - effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); - effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); - - UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType]; - effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); - effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); - - UIMotionEffectGroup *effectGroup = [UIMotionEffectGroup new]; - effectGroup.motionEffects = @[effectX, effectY]; - - // Clear old motion effect, then add new motion effects - self.hudView.motionEffects = @[]; - [self.hudView addMotionEffect:effectGroup]; -} - -- (void)updateViewHierarchy { - // Add the overlay to the application window if necessary - if(!self.controlView.superview) { - if(self.containerView){ - [self.containerView addSubview:self.controlView]; - } else { -#if !defined(SV_APP_EXTENSIONS) - [self.frontWindow addSubview:self.controlView]; -#else - // If SVProgressHUD is used inside an app extension add it to the given view - if(self.viewForExtension) { - [self.viewForExtension addSubview:self.controlView]; - } -#endif - } - } else { - // The HUD is already on screen, but maybe not in front. Therefore - // ensure that overlay will be on top of rootViewController (which may - // be changed during runtime). - [self.controlView.superview bringSubviewToFront:self.controlView]; - } - - // Add self to the overlay view - if(!self.superview) { - [self.controlView addSubview:self]; - } -} - -- (void)setStatus:(NSString*)status { - self.statusLabel.text = status; - self.statusLabel.hidden = status.length == 0; - [self updateHUDFrame]; -} - -- (void)setGraceTimer:(NSTimer*)timer { - if(_graceTimer) { - [_graceTimer invalidate]; - _graceTimer = nil; - } - if(timer) { - _graceTimer = timer; - } -} - -- (void)setFadeOutTimer:(NSTimer*)timer { - if(_fadeOutTimer) { - [_fadeOutTimer invalidate]; - _fadeOutTimer = nil; - } - if(timer) { - _fadeOutTimer = timer; - } -} - - -#pragma mark - Notifications and their handling - -- (void)registerNotifications { -#if TARGET_OS_IOS - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIApplicationDidChangeStatusBarOrientationNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIKeyboardWillHideNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIKeyboardDidHideNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIKeyboardWillShowNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIKeyboardDidShowNotification - object:nil]; -#endif - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(positionHUD:) - name:UIApplicationDidBecomeActiveNotification - object:nil]; -} - -- (NSDictionary*)notificationUserInfo { - return (self.statusLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.statusLabel.text} : nil); -} - -- (void)positionHUD:(NSNotification*)notification { - CGFloat keyboardHeight = 0.0f; - double animationDuration = 0.0; - -#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS - self.frame = [[[UIApplication sharedApplication] delegate] window].bounds; - UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation; -#elif !defined(SV_APP_EXTENSIONS) && !TARGET_OS_IOS - self.frame= [UIApplication sharedApplication].keyWindow.bounds; -#else - if (self.viewForExtension) { - self.frame = self.viewForExtension.frame; - } else { - self.frame = UIScreen.mainScreen.bounds; - } -#if TARGET_OS_IOS - UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait; -#endif -#endif - -#if TARGET_OS_IOS - // Get keyboardHeight in regard to current state - if(notification) { - NSDictionary* keyboardInfo = [notification userInfo]; - CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; - animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - - if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) { - keyboardHeight = CGRectGetWidth(keyboardFrame); - - if(UIInterfaceOrientationIsPortrait(orientation)) { - keyboardHeight = CGRectGetHeight(keyboardFrame); - } - } - } else { - keyboardHeight = self.visibleKeyboardHeight; - } -#endif - - // Get the currently active frame of the display (depends on orientation) - CGRect orientationFrame = self.bounds; - -#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS - CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame; -#else - CGRect statusBarFrame = CGRectZero; -#endif - -#if TARGET_OS_IOS - // Update the motion effects in regard to orientation - [self updateMotionEffectForOrientation:orientation]; -#else - [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; -#endif - - // Calculate available height for display - CGFloat activeHeight = CGRectGetHeight(orientationFrame); - if(keyboardHeight > 0) { - activeHeight += CGRectGetHeight(statusBarFrame) * 2; - } - activeHeight -= keyboardHeight; - - CGFloat posX = CGRectGetMidX(orientationFrame); - CGFloat posY = floorf(activeHeight*0.45f); - - CGFloat rotateAngle = 0.0; - CGPoint newCenter = CGPointMake(posX, posY); - - if(notification) { - // Animate update if notification was present - [UIView animateWithDuration:animationDuration - delay:0 - options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) - animations:^{ - [self moveToPoint:newCenter rotateAngle:rotateAngle]; - [self.hudView setNeedsDisplay]; - } completion:nil]; - } else { - [self moveToPoint:newCenter rotateAngle:rotateAngle]; - } -} - -- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle { - self.hudView.transform = CGAffineTransformMakeRotation(angle); - if (self.containerView) { - self.hudView.center = CGPointMake(self.containerView.center.x + self.offsetFromCenter.horizontal, self.containerView.center.y + self.offsetFromCenter.vertical); - } else { - self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical); - } -} - - -#pragma mark - Event handling - -- (void)controlViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event { - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification - object:self - userInfo:[self notificationUserInfo]]; - - UITouch *touch = event.allTouches.anyObject; - CGPoint touchLocation = [touch locationInView:self]; - - if(CGRectContainsPoint(self.hudView.frame, touchLocation)) { - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidTouchDownInsideNotification - object:self - userInfo:[self notificationUserInfo]]; - } -} - - -#pragma mark - Master show/dismiss methods - -- (void)showProgress:(float)progress status:(NSString*)status { - __weak SVProgressHUD *weakSelf = self; - [[NSOperationQueue mainQueue] addOperationWithBlock:^{ - __strong SVProgressHUD *strongSelf = weakSelf; - if(strongSelf){ - if(strongSelf.fadeOutTimer) { - strongSelf.activityCount = 0; - } - - // Stop timer - strongSelf.fadeOutTimer = nil; - strongSelf.graceTimer = nil; - - // Update / Check view hierarchy to ensure the HUD is visible - [strongSelf updateViewHierarchy]; - - // Reset imageView and fadeout timer if an image is currently displayed - strongSelf.imageView.hidden = YES; - strongSelf.imageView.image = nil; - - // Update text and set progress to the given value - strongSelf.statusLabel.hidden = status.length == 0; - strongSelf.statusLabel.text = status; - strongSelf.progress = progress; - - // Choose the "right" indicator depending on the progress - if(progress >= 0) { - // Cancel the indefiniteAnimatedView, then show the ringLayer - [strongSelf cancelIndefiniteAnimatedViewAnimation]; - - // Add ring to HUD - if(!strongSelf.ringView.superview){ - [strongSelf.hudView.contentView addSubview:strongSelf.ringView]; - } - if(!strongSelf.backgroundRingView.superview){ - [strongSelf.hudView.contentView addSubview:strongSelf.backgroundRingView]; - } - - // Set progress animated - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - strongSelf.ringView.strokeEnd = progress; - [CATransaction commit]; - - // Update the activity count - if(progress == 0) { - strongSelf.activityCount++; - } - } else { - // Cancel the ringLayer animation, then show the indefiniteAnimatedView - [strongSelf cancelRingLayerAnimation]; - - // Add indefiniteAnimatedView to HUD - [strongSelf.hudView.contentView addSubview:strongSelf.indefiniteAnimatedView]; - if([strongSelf.indefiniteAnimatedView respondsToSelector:@selector(startAnimating)]) { - [(id)strongSelf.indefiniteAnimatedView startAnimating]; - } - - // Update the activity count - strongSelf.activityCount++; - } - - // Fade in delayed if a grace time is set - if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) { - strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:nil repeats:NO]; - [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes]; - } else { - [strongSelf fadeIn:nil]; - } - - // Tell the Haptics Generator to prepare for feedback, which may come soon -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 - if (@available(iOS 10.0, *)) { - [strongSelf.hapticGenerator prepare]; - } -#endif - } - }]; -} - -- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration { - __weak SVProgressHUD *weakSelf = self; - [[NSOperationQueue mainQueue] addOperationWithBlock:^{ - __strong SVProgressHUD *strongSelf = weakSelf; - if(strongSelf){ - // Stop timer - strongSelf.fadeOutTimer = nil; - strongSelf.graceTimer = nil; - - // Update / Check view hierarchy to ensure the HUD is visible - [strongSelf updateViewHierarchy]; - - // Reset progress and cancel any running animation - strongSelf.progress = SVProgressHUDUndefinedProgress; - [strongSelf cancelRingLayerAnimation]; - [strongSelf cancelIndefiniteAnimatedViewAnimation]; - - // Update imageView - if (self.shouldTintImages) { - if (image.renderingMode != UIImageRenderingModeAlwaysTemplate) { - strongSelf.imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - } - strongSelf.imageView.tintColor = strongSelf.foregroundColorForStyle;; - } else { - strongSelf.imageView.image = image; - } - strongSelf.imageView.hidden = NO; - - // Update text - strongSelf.statusLabel.hidden = status.length == 0; - strongSelf.statusLabel.text = status; - - // Fade in delayed if a grace time is set - // An image will be dismissed automatically. Thus pass the duration as userInfo. - if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) { - strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:@(duration) repeats:NO]; - [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes]; - } else { - [strongSelf fadeIn:@(duration)]; - } - } - }]; -} - -- (void)fadeIn:(id)data { - // Update the HUDs frame to the new content and position HUD - [self updateHUDFrame]; - [self positionHUD:nil]; - - // Update accessibility as well as user interaction - if(self.defaultMaskType != SVProgressHUDMaskTypeNone) { - self.controlView.userInteractionEnabled = YES; - self.accessibilityLabel = self.statusLabel.text ?: NSLocalizedString(@"Loading", nil); - self.isAccessibilityElement = YES; - } else { - self.controlView.userInteractionEnabled = NO; - self.hudView.accessibilityLabel = self.statusLabel.text ?: NSLocalizedString(@"Loading", nil); - self.hudView.isAccessibilityElement = YES; - } - - // Get duration - id duration = [data isKindOfClass:[NSTimer class]] ? ((NSTimer *)data).userInfo : data; - - // Show if not already visible - if(self.backgroundView.alpha != 1.0f) { - // Post notification to inform user - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification - object:self - userInfo:[self notificationUserInfo]]; - - // Shrink HUD to to make a nice appear / pop up animation - self.hudView.transform = self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1/1.5f, 1/1.5f); - - __block void (^animationsBlock)(void) = ^{ - // Zoom HUD a little to make a nice appear / pop up animation - self.hudView.transform = CGAffineTransformIdentity; - - // Fade in all effects (colors, blur, etc.) - [self fadeInEffects]; - }; - - __block void (^completionBlock)(void) = ^{ - // Check if we really achieved to show the HUD (<=> alpha) - // and the change of these values has not been cancelled in between e.g. due to a dismissal - if(self.backgroundView.alpha == 1.0f){ - // Register observer <=> we now have to handle orientation changes etc. - [self registerNotifications]; - - // Post notification to inform user - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification - object:self - userInfo:[self notificationUserInfo]]; - - // Update accessibility - UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text); - - // Dismiss automatically if a duration was passed as userInfo. We start a timer - // which then will call dismiss after the predefined duration - if(duration){ - self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO]; - [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes]; - } - } - }; - - // Animate appearance - if (self.fadeInAnimationDuration > 0) { - // Animate appearance - [UIView animateWithDuration:self.fadeInAnimationDuration - delay:0 - options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) - animations:^{ - animationsBlock(); - } completion:^(BOOL finished) { - completionBlock(); - }]; - } else { - animationsBlock(); - completionBlock(); - } - - // Inform iOS to redraw the view hierarchy - [self setNeedsDisplay]; - } else { - // Update accessibility - UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text); - - // Dismiss automatically if a duration was passed as userInfo. We start a timer - // which then will call dismiss after the predefined duration - if(duration){ - self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO]; - [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes]; - } - } -} - -- (void)dismiss { - [self dismissWithDelay:0.0 completion:nil]; -} - -- (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { - __weak SVProgressHUD *weakSelf = self; - [[NSOperationQueue mainQueue] addOperationWithBlock:^{ - __strong SVProgressHUD *strongSelf = weakSelf; - if(strongSelf){ - // Stop timer - strongSelf.graceTimer = nil; - - // Post notification to inform user - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification - object:nil - userInfo:[strongSelf notificationUserInfo]]; - - // Reset activity count - strongSelf.activityCount = 0; - - __block void (^animationsBlock)(void) = ^{ - // Shrink HUD a little to make a nice disappear animation - strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f); - - // Fade out all effects (colors, blur, etc.) - [strongSelf fadeOutEffects]; - }; - - __block void (^completionBlock)(void) = ^{ - // Check if we really achieved to dismiss the HUD (<=> alpha values are applied) - // and the change of these values has not been cancelled in between e.g. due to a new show - if(self.backgroundView.alpha == 0.0f){ - // Clean up view hierarchy (overlays) - [strongSelf.controlView removeFromSuperview]; - [strongSelf.backgroundView removeFromSuperview]; - [strongSelf.hudView removeFromSuperview]; - [strongSelf removeFromSuperview]; - - // Reset progress and cancel any running animation - strongSelf.progress = SVProgressHUDUndefinedProgress; - [strongSelf cancelRingLayerAnimation]; - [strongSelf cancelIndefiniteAnimatedViewAnimation]; - - // Remove observer <=> we do not have to handle orientation changes etc. - [[NSNotificationCenter defaultCenter] removeObserver:strongSelf]; - - // Post notification to inform user - [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification - object:strongSelf - userInfo:[strongSelf notificationUserInfo]]; - - // Tell the rootViewController to update the StatusBar appearance -#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS - UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController; - [rootController setNeedsStatusBarAppearanceUpdate]; -#endif - - // Run an (optional) completionHandler - if (completion) { - completion(); - } - } - }; - - // UIViewAnimationOptionBeginFromCurrentState AND a delay doesn't always work as expected - // When UIViewAnimationOptionBeginFromCurrentState is set, animateWithDuration: evaluates the current - // values to check if an animation is necessary. The evaluation happens at function call time and not - // after the delay => the animation is sometimes skipped. Therefore we delay using dispatch_after. - - dispatch_time_t dipatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)); - dispatch_after(dipatchTime, dispatch_get_main_queue(), ^{ - if (strongSelf.fadeOutAnimationDuration > 0) { - // Animate appearance - [UIView animateWithDuration:strongSelf.fadeOutAnimationDuration - delay:0 - options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) - animations:^{ - animationsBlock(); - } completion:^(BOOL finished) { - completionBlock(); - }]; - } else { - animationsBlock(); - completionBlock(); - } - }); - - // Inform iOS to redraw the view hierarchy - [strongSelf setNeedsDisplay]; - } - }]; -} - - -#pragma mark - Ring progress animation - -- (UIView*)indefiniteAnimatedView { - // Get the correct spinner for defaultAnimationType - if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat){ - // Check if spinner exists and is an object of different class - if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[SVIndefiniteAnimatedView class]]){ - [_indefiniteAnimatedView removeFromSuperview]; - _indefiniteAnimatedView = nil; - } - - if(!_indefiniteAnimatedView){ - _indefiniteAnimatedView = [[SVIndefiniteAnimatedView alloc] initWithFrame:CGRectZero]; - } - - // Update styling - SVIndefiniteAnimatedView *indefiniteAnimatedView = (SVIndefiniteAnimatedView*)_indefiniteAnimatedView; - indefiniteAnimatedView.strokeColor = self.foregroundColorForStyle; - indefiniteAnimatedView.strokeThickness = self.ringThickness; - indefiniteAnimatedView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; - } else { - // Check if spinner exists and is an object of different class - if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[UIActivityIndicatorView class]]){ - [_indefiniteAnimatedView removeFromSuperview]; - _indefiniteAnimatedView = nil; - } - - if(!_indefiniteAnimatedView){ - _indefiniteAnimatedView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - } - - // Update styling - UIActivityIndicatorView *activityIndicatorView = (UIActivityIndicatorView*)_indefiniteAnimatedView; - activityIndicatorView.color = self.foregroundColorForStyle; - } - [_indefiniteAnimatedView sizeToFit]; - - return _indefiniteAnimatedView; -} - -- (SVProgressAnimatedView*)ringView { - if(!_ringView) { - _ringView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; - } - - // Update styling - _ringView.strokeColor = self.foregroundColorForStyle; - _ringView.strokeThickness = self.ringThickness; - _ringView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; - - return _ringView; -} - -- (SVProgressAnimatedView*)backgroundRingView { - if(!_backgroundRingView) { - _backgroundRingView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; - _backgroundRingView.strokeEnd = 1.0f; - } - - // Update styling - _backgroundRingView.strokeColor = [self.foregroundColorForStyle colorWithAlphaComponent:0.1f]; - _backgroundRingView.strokeThickness = self.ringThickness; - _backgroundRingView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; - - return _backgroundRingView; -} - -- (void)cancelRingLayerAnimation { - // Animate value update, stop animation - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - [self.hudView.layer removeAllAnimations]; - self.ringView.strokeEnd = 0.0f; - - [CATransaction commit]; - - // Remove from view - [self.ringView removeFromSuperview]; - [self.backgroundRingView removeFromSuperview]; -} - -- (void)cancelIndefiniteAnimatedViewAnimation { - // Stop animation - if([self.indefiniteAnimatedView respondsToSelector:@selector(stopAnimating)]) { - [(id)self.indefiniteAnimatedView stopAnimating]; - } - // Remove from view - [self.indefiniteAnimatedView removeFromSuperview]; -} - - -#pragma mark - Utilities - -+ (BOOL)isVisible { - // Checking one alpha value is sufficient as they are all the same - return [self sharedView].backgroundView.alpha > 0.0f; -} - - -#pragma mark - Getters - -+ (NSTimeInterval)displayDurationForString:(NSString*)string { - CGFloat minimum = MAX((CGFloat)string.length * 0.06 + 0.5, [self sharedView].minimumDismissTimeInterval); - return MIN(minimum, [self sharedView].maximumDismissTimeInterval); -} - -- (UIColor*)foregroundColorForStyle { - if(self.defaultStyle == SVProgressHUDStyleLight) { - return [UIColor blackColor]; - } else if(self.defaultStyle == SVProgressHUDStyleDark) { - return [UIColor whiteColor]; - } else { - return self.foregroundColor; - } -} - -- (UIColor*)backgroundColorForStyle { - if(self.defaultStyle == SVProgressHUDStyleLight) { - return [UIColor whiteColor]; - } else if(self.defaultStyle == SVProgressHUDStyleDark) { - return [UIColor blackColor]; - } else { - return self.backgroundColor; - } -} - -- (UIControl*)controlView { - if(!_controlView) { - _controlView = [UIControl new]; - _controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _controlView.backgroundColor = [UIColor clearColor]; - _controlView.userInteractionEnabled = YES; - [_controlView addTarget:self action:@selector(controlViewDidReceiveTouchEvent:forEvent:) forControlEvents:UIControlEventTouchDown]; - } - - // Update frames -#if !defined(SV_APP_EXTENSIONS) - CGRect windowBounds = [[[UIApplication sharedApplication] delegate] window].bounds; - _controlView.frame = windowBounds; -#else - _controlView.frame = [UIScreen mainScreen].bounds; -#endif - - return _controlView; -} - --(UIView *)backgroundView { - if(!_backgroundView){ - _backgroundView = [UIView new]; - _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - } - if(!_backgroundView.superview){ - [self insertSubview:_backgroundView belowSubview:self.hudView]; - } - - // Update styling - if(self.defaultMaskType == SVProgressHUDMaskTypeGradient){ - if(!_backgroundRadialGradientLayer){ - _backgroundRadialGradientLayer = [SVRadialGradientLayer layer]; - } - if(!_backgroundRadialGradientLayer.superlayer){ - [_backgroundView.layer insertSublayer:_backgroundRadialGradientLayer atIndex:0]; - } - _backgroundView.backgroundColor = [UIColor clearColor]; - } else { - if(_backgroundRadialGradientLayer && _backgroundRadialGradientLayer.superlayer){ - [_backgroundRadialGradientLayer removeFromSuperlayer]; - } - if(self.defaultMaskType == SVProgressHUDMaskTypeBlack){ - _backgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; - } else if(self.defaultMaskType == SVProgressHUDMaskTypeCustom){ - _backgroundView.backgroundColor = self.backgroundLayerColor; - } else { - _backgroundView.backgroundColor = [UIColor clearColor]; - } - } - - // Update frame - if(_backgroundView){ - _backgroundView.frame = self.bounds; - } - if(_backgroundRadialGradientLayer){ - _backgroundRadialGradientLayer.frame = self.bounds; - - // Calculate the new center of the gradient, it may change if keyboard is visible - CGPoint gradientCenter = self.center; - gradientCenter.y = (self.bounds.size.height - self.visibleKeyboardHeight)/2; - _backgroundRadialGradientLayer.gradientCenter = gradientCenter; - [_backgroundRadialGradientLayer setNeedsDisplay]; - } - - return _backgroundView; -} -- (UIVisualEffectView*)hudView { - if(!_hudView) { - _hudView = [UIVisualEffectView new]; - _hudView.layer.masksToBounds = YES; - _hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; - } - if(!_hudView.superview) { - [self addSubview:_hudView]; - } - - // Update styling - _hudView.layer.cornerRadius = self.cornerRadius; - - return _hudView; -} - -- (UILabel*)statusLabel { - if(!_statusLabel) { - _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _statusLabel.backgroundColor = [UIColor clearColor]; - _statusLabel.adjustsFontSizeToFitWidth = YES; - _statusLabel.textAlignment = NSTextAlignmentCenter; - _statusLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; - _statusLabel.numberOfLines = 0; - } - if(!_statusLabel.superview) { - [self.hudView.contentView addSubview:_statusLabel]; - } - - // Update styling - _statusLabel.textColor = self.foregroundColorForStyle; - _statusLabel.font = self.font; - - return _statusLabel; -} - -- (UIImageView*)imageView { - if(_imageView && !CGSizeEqualToSize(_imageView.bounds.size, _imageViewSize)) { - [_imageView removeFromSuperview]; - _imageView = nil; - } - - if(!_imageView) { - _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, _imageViewSize.width, _imageViewSize.height)]; - } - if(!_imageView.superview) { - [self.hudView.contentView addSubview:_imageView]; - } - - return _imageView; -} - - -#pragma mark - Helper - -- (CGFloat)visibleKeyboardHeight { -#if !defined(SV_APP_EXTENSIONS) - UIWindow *keyboardWindow = nil; - for (UIWindow *testWindow in UIApplication.sharedApplication.windows) { - if(![testWindow.class isEqual:UIWindow.class]) { - keyboardWindow = testWindow; - break; - } - } - - for (__strong UIView *possibleKeyboard in keyboardWindow.subviews) { - NSString *viewName = NSStringFromClass(possibleKeyboard.class); - if([viewName hasPrefix:@"UI"]){ - if([viewName hasSuffix:@"PeripheralHostView"] || [viewName hasSuffix:@"Keyboard"]){ - return CGRectGetHeight(possibleKeyboard.bounds); - } else if ([viewName hasSuffix:@"InputSetContainerView"]){ - for (__strong UIView *possibleKeyboardSubview in possibleKeyboard.subviews) { - viewName = NSStringFromClass(possibleKeyboardSubview.class); - if([viewName hasPrefix:@"UI"] && [viewName hasSuffix:@"InputSetHostView"]) { - CGRect convertedRect = [possibleKeyboard convertRect:possibleKeyboardSubview.frame toView:self]; - CGRect intersectedRect = CGRectIntersection(convertedRect, self.bounds); - if (!CGRectIsNull(intersectedRect)) { - return CGRectGetHeight(intersectedRect); - } - } - } - } - } - } -#endif - return 0; -} - -- (UIWindow *)frontWindow { -#if !defined(SV_APP_EXTENSIONS) - NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator]; - for (UIWindow *window in frontToBackWindows) { - BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen; - BOOL windowIsVisible = !window.hidden && window.alpha > 0; - BOOL windowLevelSupported = (window.windowLevel >= UIWindowLevelNormal && window.windowLevel <= self.maxSupportedWindowLevel); - BOOL windowKeyWindow = window.isKeyWindow; - - if(windowOnMainScreen && windowIsVisible && windowLevelSupported && windowKeyWindow) { - return window; - } - } -#endif - return nil; -} - -- (void)fadeInEffects { - if(self.defaultStyle != SVProgressHUDStyleCustom) { - // Add blur effect - UIBlurEffectStyle blurEffectStyle = self.defaultStyle == SVProgressHUDStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight; - UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:blurEffectStyle]; - self.hudView.effect = blurEffect; - - // We omit UIVibrancy effect and use a suitable background color as an alternative. - // This will make everything more readable. See the following for details: - // https://www.omnigroup.com/developer/how-to-make-text-in-a-uivisualeffectview-readable-on-any-background - - self.hudView.backgroundColor = [self.backgroundColorForStyle colorWithAlphaComponent:0.6f]; - } else { - self.hudView.backgroundColor = self.backgroundColorForStyle; - } - - // Fade in views - self.backgroundView.alpha = 1.0f; - - self.imageView.alpha = 1.0f; - self.statusLabel.alpha = 1.0f; - self.indefiniteAnimatedView.alpha = 1.0f; - self.ringView.alpha = self.backgroundRingView.alpha = 1.0f; -} - -- (void)fadeOutEffects -{ - if(self.defaultStyle != SVProgressHUDStyleCustom) { - // Remove blur effect - self.hudView.effect = nil; - } - - // Remove background color - self.hudView.backgroundColor = [UIColor clearColor]; - - // Fade out views - self.backgroundView.alpha = 0.0f; - - self.imageView.alpha = 0.0f; - self.statusLabel.alpha = 0.0f; - self.indefiniteAnimatedView.alpha = 0.0f; - self.ringView.alpha = self.backgroundRingView.alpha = 0.0f; -} - -#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 -- (UINotificationFeedbackGenerator *)hapticGenerator NS_AVAILABLE_IOS(10_0) { - // Only return if haptics are enabled - if(!self.hapticsEnabled) { - return nil; - } - - if(!_hapticGenerator) { - _hapticGenerator = [[UINotificationFeedbackGenerator alloc] init]; - } - return _hapticGenerator; -} -#endif - - -#pragma mark - UIAppearance Setters - -- (void)setDefaultStyle:(SVProgressHUDStyle)style { - if (!_isInitializing) _defaultStyle = style; -} - -- (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { - if (!_isInitializing) _defaultMaskType = maskType; -} - -- (void)setDefaultAnimationType:(SVProgressHUDAnimationType)animationType { - if (!_isInitializing) _defaultAnimationType = animationType; -} - -- (void)setContainerView:(UIView *)containerView { - if (!_isInitializing) _containerView = containerView; -} - -- (void)setMinimumSize:(CGSize)minimumSize { - if (!_isInitializing) _minimumSize = minimumSize; -} - -- (void)setRingThickness:(CGFloat)ringThickness { - if (!_isInitializing) _ringThickness = ringThickness; -} - -- (void)setRingRadius:(CGFloat)ringRadius { - if (!_isInitializing) _ringRadius = ringRadius; -} - -- (void)setRingNoTextRadius:(CGFloat)ringNoTextRadius { - if (!_isInitializing) _ringNoTextRadius = ringNoTextRadius; -} - -- (void)setCornerRadius:(CGFloat)cornerRadius { - if (!_isInitializing) _cornerRadius = cornerRadius; -} - -- (void)setFont:(UIFont*)font { - if (!_isInitializing) _font = font; -} - -- (void)setForegroundColor:(UIColor*)color { - if (!_isInitializing) _foregroundColor = color; -} - -- (void)setBackgroundColor:(UIColor*)color { - if (!_isInitializing) _backgroundColor = color; -} - -- (void)setBackgroundLayerColor:(UIColor*)color { - if (!_isInitializing) _backgroundLayerColor = color; -} - -- (void)setShouldTintImages:(BOOL)shouldTintImages { - if (!_isInitializing) _shouldTintImages = shouldTintImages; -} - -- (void)setInfoImage:(UIImage*)image { - if (!_isInitializing) _infoImage = image; -} - -- (void)setSuccessImage:(UIImage*)image { - if (!_isInitializing) _successImage = image; -} - -- (void)setErrorImage:(UIImage*)image { - if (!_isInitializing) _errorImage = image; -} - -- (void)setViewForExtension:(UIView*)view { - if (!_isInitializing) _viewForExtension = view; -} - -- (void)setOffsetFromCenter:(UIOffset)offset { - if (!_isInitializing) _offsetFromCenter = offset; -} - -- (void)setMinimumDismissTimeInterval:(NSTimeInterval)minimumDismissTimeInterval { - if (!_isInitializing) _minimumDismissTimeInterval = minimumDismissTimeInterval; -} - -- (void)setFadeInAnimationDuration:(NSTimeInterval)duration { - if (!_isInitializing) _fadeInAnimationDuration = duration; -} - -- (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { - if (!_isInitializing) _fadeOutAnimationDuration = duration; -} - -- (void)setMaxSupportedWindowLevel:(UIWindowLevel)maxSupportedWindowLevel { - if (!_isInitializing) _maxSupportedWindowLevel = maxSupportedWindowLevel; -} - -@end diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.h b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.h deleted file mode 100755 index 68d452a27..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// SVRadialGradientLayer.h -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2014-2018 Tobias Tiemerding. All rights reserved. -// - -#import - -@interface SVRadialGradientLayer : CALayer - -@property (nonatomic) CGPoint gradientCenter; - -@end diff --git a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.m b/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.m deleted file mode 100755 index c62e0f85c..000000000 --- a/arcgis-ios-sdk-samples/Shared resources/Libraries/SVProgressHUD/SVRadialGradientLayer.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// SVRadialGradientLayer.m -// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD -// -// Copyright (c) 2014-2018 Tobias Tiemerding. All rights reserved. -// - -#import "SVRadialGradientLayer.h" - -@implementation SVRadialGradientLayer - -- (void)drawInContext:(CGContextRef)context { - size_t locationsCount = 2; - CGFloat locations[2] = {0.0f, 1.0f}; - CGFloat colors[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f}; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); - CGColorSpaceRelease(colorSpace); - - float radius = MIN(self.bounds.size.width , self.bounds.size.height); - CGContextDrawRadialGradient (context, gradient, self.gradientCenter, 0, self.gradientCenter, radius, kCGGradientDrawsAfterEndLocation); - CGGradientRelease(gradient); -} - -@end diff --git a/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/ConfigureSubnetworkTraceViewController.swift b/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/ConfigureSubnetworkTraceViewController.swift index 18ddb461f..b68274c4b 100644 --- a/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/ConfigureSubnetworkTraceViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Configure subnetwork trace/ConfigureSubnetworkTraceViewController.swift @@ -100,9 +100,9 @@ class ConfigureSubnetworkTraceViewController: UIViewController { } // Trace the utility network. - SVProgressHUD.show(withStatus: "Tracing…") + UIApplication.shared.showProgressHUD(message: "Tracing…") utilityNetwork.trace(with: parameters) { [weak self] (results, error) in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } if let error = error { self.presentAlert(error: error) @@ -145,11 +145,11 @@ class ConfigureSubnetworkTraceViewController: UIViewController { let tierName = "Medium Voltage Radial" // Load the utility network. - SVProgressHUD.show(withStatus: "Loading utility network…") + UIApplication.shared.showProgressHUD(message: "Loading utility network…") // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. utilityNetwork.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") utilityNetwork.load { [weak self] error in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } if let error = error { self.presentAlert(error: error) 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 index 5bee44bc6..a2a240041 100644 --- a/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Create load report/CreateLoadReportViewController.swift @@ -63,12 +63,12 @@ class CreateLoadReportViewController: UIViewController { /// Load the utility network. func loadUtilityNetwork() { - SVProgressHUD.show(withStatus: "Loading utility network…") + UIApplication.shared.showProgressHUD(message: "Loading utility network…") // NOTE: Never hardcode login information in a production application. // This is done solely for the sake of the sample. utilityNetwork.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") utilityNetwork.load { [weak self] error in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } guard error == nil else { self.presentAlert(error: error!) @@ -97,9 +97,9 @@ class CreateLoadReportViewController: UIViewController { // Set the default expression. initialExpression = traceConfiguration.traversability?.barriers as? AGSUtilityTraceConditionalExpression - // Create downstream trace parameters with function outputs. + // Create downstream trace parameters with elements and function outputs. let traceParameters = AGSUtilityTraceParameters(traceType: .downstream, startingLocations: [startingLocation]) - traceParameters.resultTypes.append(.ags_value(with: .functionOutputs)) + traceParameters.resultTypes = [.ags_value(with: .elements), .ags_value(with: .functionOutputs)] // The service category for counting total customers. if let serviceCategory = utilityNetwork.definition.categories.first(where: { $0.name == "ServicePoint" }), @@ -173,7 +173,7 @@ class CreateLoadReportViewController: UIViewController { } @IBAction func runBarButtonItemTapped(_ sender: UIBarButtonItem) { - SVProgressHUD.show(withStatus: "Creating load report…") + UIApplication.shared.showProgressHUD(message: "Creating load report…") let traceGroup = DispatchGroup() var summaries = [AGSCodedValue: PhaseSummary]() @@ -208,7 +208,7 @@ class CreateLoadReportViewController: UIViewController { } // Reload the load report table when trace completes. traceGroup.notify(queue: .main) { [weak self] in - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() guard let self = self else { return } self.summaries = summaries self.tableView.reloadSection(.included) diff --git a/arcgis-ios-sdk-samples/Utility network/Display utility associations/DisplayUtilityAssociationsViewController.swift b/arcgis-ios-sdk-samples/Utility network/Display utility associations/DisplayUtilityAssociationsViewController.swift index 534fce7ee..e9f0c23c4 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display utility associations/DisplayUtilityAssociationsViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Display utility associations/DisplayUtilityAssociationsViewController.swift @@ -20,6 +20,8 @@ class DisplayUtilityAssociationsViewController: UIViewController { @IBOutlet var mapView: AGSMapView! { didSet { let map = AGSMap(basemapStyle: .arcGISTopographic) + // Add the utility network to the map. + map.utilityNetworks.add(utilityNetwork) mapView.map = map mapView.setViewpoint(AGSViewpoint(latitude: 41.8057655, longitude: -88.1489692, scale: 70.5310735)) mapView.graphicsOverlays.add(associationsOverlay) @@ -141,13 +143,8 @@ class DisplayUtilityAssociationsViewController: UIViewController { let connectivityBBI = UIBarButtonItem(image: connectivityImage, style: .plain, target: nil, action: nil) let attachmentLabel = UIBarButtonItem(title: "Attachment", style: .plain, target: nil, action: nil) let connectivityLabel = UIBarButtonItem(title: "Connectivity", style: .plain, target: nil, action: nil) - if #available(iOS 13.0, *) { - attachmentLabel.tintColor = .label - connectivityLabel.tintColor = .label - } else { - attachmentLabel.tintColor = .black - connectivityLabel.tintColor = .black - } + attachmentLabel.tintColor = .label + connectivityLabel.tintColor = .label let fixedSpace1 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) let fixedSpace2 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) let flexibleSpace1 = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) diff --git a/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.md b/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.md index cb8321312..25e73d3be 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.md +++ b/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.md @@ -14,7 +14,7 @@ Pan and zoom around the map. Observe graphics that show utility associations bet ## How it works -1. Create and load an `AGSUtilityNetwork` with a feature service URL. +1. Create an `AGSUtilityNetwork` with a feature service URL, add it to the map's `utilityNetworks` array, then load it. 2. Add an `AGSFeatureLayer` to the map for every `AGSUtilityNetworkSource` of type `edge` or `junction`. 3. Create an `AGSGraphicsOverlay` for the utility associations. 4. When the sample is opened and every time the viewpoint changes, do the following steps. @@ -27,6 +27,7 @@ Pan and zoom around the map. Observe graphics that show utility associations bet ## Relevant API * AGSGraphicsOverlay +* AGSServiceGeodatabase * AGSUtilityAssociation * AGSUtilityAssociationType * AGSUtilityNetwork diff --git a/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.metadata.json index b718f998c..b99bf9746 100644 --- a/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Display utility associations/README.metadata.json @@ -13,6 +13,7 @@ "containment", "relationships", "AGSGraphicsOverlay", + "AGSServiceGeodatabase", "AGSUtilityAssociation", "AGSUtilityAssociationType", "AGSUtilityNetwork" @@ -21,6 +22,7 @@ ], "relevant_apis": [ "AGSGraphicsOverlay", + "AGSServiceGeodatabase", "AGSUtilityAssociation", "AGSUtilityAssociationType", "AGSUtilityNetwork" diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTraceViewController.swift b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTraceViewController.swift index 252ff0cf3..29c340dbf 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTraceViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/PerformValveIsolationTraceViewController.swift @@ -29,14 +29,14 @@ class PerformValveIsolationTraceViewController: UIViewController { /// The map view managed by the view controller. @IBOutlet weak var mapView: AGSMapView! { didSet { - mapView.map = makeMap(with: layers) + mapView.map = makeMap() } } // MARK: Instance properties /// The URL to the feature service for running the isolation trace. - let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleGas/FeatureServer")! + static let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleGas/FeatureServer")! // Constants for creating the default trace configuration. let domainNetworkName = "Pipeline" @@ -53,30 +53,19 @@ class PerformValveIsolationTraceViewController: UIViewController { var traceConfiguration: AGSUtilityTraceConfiguration? var selectedCategory: AGSUtilityCategory? var startingLocationElement: AGSUtilityElement! - var utilityNetwork: AGSUtilityNetwork! - - /// The gas line layer ./3 and gas device layer ./0 are created from the feature service URL. - lazy var layers: [AGSFeatureLayer] = { - let urls = [ - featureServiceURL.appendingPathComponent("3"), - featureServiceURL.appendingPathComponent("0") - ] - return urls.map { (url) -> AGSFeatureLayer in - let featureTable = AGSServiceFeatureTable(url: url) - return AGSFeatureLayer(featureTable: featureTable) - } - }() + let utilityNetwork = AGSUtilityNetwork(url: featureServiceURL) + let serviceGeodatabase = AGSServiceGeodatabase(url: featureServiceURL) + var layers = [AGSFeatureLayer]() // MARK: Initialize map and utility network /// Create a map. /// /// - Parameter layers: The feature layers for the utility network. - /// - Returns: An `AGSMap` object. - func makeMap(with layers: [AGSFeatureLayer]) -> AGSMap { + func makeMap() -> AGSMap { let map = AGSMap(basemapStyle: .arcGISStreetsNight) - // Add the utility network feature layers to the map for display. - map.operationalLayers.addObjects(from: layers) + // Add the utility network to the map's array of utility networks. + map.utilityNetworks.add(utilityNetwork) return map } @@ -104,10 +93,28 @@ class PerformValveIsolationTraceViewController: UIViewController { return parameters } + /// Load the service geodatabase and initialize the layers. + func loadServiceGeodatabase() { + // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. + serviceGeodatabase.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") + serviceGeodatabase.load { [weak self] error in + guard let self = self else { return } + // The gas device layer ./0 and gas line layer ./3 are created from the service geodatabase. + if let gasDeviceLayerTable = self.serviceGeodatabase.table(withLayerID: 0), + let gasLineLayerTable = self.serviceGeodatabase.table(withLayerID: 3) { + self.layers = [gasLineLayerTable, gasDeviceLayerTable].map(AGSFeatureLayer.init) + // Add the utility network feature layers to the map for display. + self.mapView.map?.operationalLayers.addObjects(from: self.layers) + self.loadUtilityNetwork() + } else if let error = error { + self.presentAlert(error: error) + } + } + } + + /// Load the utility network. func loadUtilityNetwork() { setStatus(message: "Loading utility network…") - // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. - utilityNetwork.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") // Load the utility network to be ready to run a trace against it. utilityNetwork.load { [weak self] error in guard let self = self else { return } @@ -153,7 +160,7 @@ class PerformValveIsolationTraceViewController: UIViewController { let selectionGroup = DispatchGroup() groupedElements.forEach { (networkName, elements) in - guard let layer = self.layers.first(where: { $0.featureTable?.tableName == networkName }) else { return } + guard let layer = layers.first(where: { $0.featureTable?.tableName == networkName }) else { return } selectionGroup.enter() self.utilityNetwork.features(for: elements) { [weak self, layer] (features, error) in @@ -188,6 +195,7 @@ class PerformValveIsolationTraceViewController: UIViewController { startingLocationGraphicsOverlay.graphics.add(startingLocationGraphic) self.mapView.graphicsOverlays.add(startingLocationGraphicsOverlay) self.mapView.setViewpoint(AGSViewpoint(center: startingLocationGeometry, scale: 3000), completion: nil) + self.setStatus(message: "Use the toolbar to change the attributes.") } else { self.setStatus(message: "Drawing starting location feature failed.") } @@ -223,24 +231,24 @@ class PerformValveIsolationTraceViewController: UIViewController { @IBAction func traceButtonTapped(_ button: UIBarButtonItem) { clearLayersSelection() guard let parameters = makeTraceParameters() else { return } - SVProgressHUD.show(withStatus: "Running isolation trace…") + UIApplication.shared.showProgressHUD(message: "Running isolation trace…") utilityNetwork.trace(with: parameters) { [weak self] (traceResults, error) in guard let self = self else { return } let categoryName = self.selectedCategory!.name.lowercased() if let elementTraceResult = traceResults?.first as? AGSUtilityElementTraceResult, - !elementTraceResult.elements.isEmpty { - SVProgressHUD.show(withStatus: "Trace completed. Selecting features…") + !elementTraceResult.elements.isEmpty { + UIApplication.shared.showProgressHUD(message: "Trace completed. Selecting features…") self.selectFeatures(in: elementTraceResult.elements) { [weak self] in self?.setStatus(message: "Trace with \(categoryName) category completed.") - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } else if let error = error { self.setStatus(message: "Trace with \(categoryName) category failed.") self.presentAlert(error: error) - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } else { self.setStatus(message: "Trace with \(categoryName) category completed with no output.") - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } @@ -268,10 +276,9 @@ class PerformValveIsolationTraceViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + + loadServiceGeodatabase() // Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["PerformValveIsolationTraceViewController"] - // Create the utility network, referencing the map. - utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: mapView.map!) - loadUtilityNetwork() } } 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 ac7619433..da763e998 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 @@ -15,24 +15,26 @@ Tap "Category" to create and set the configuration's filter barriers with a util ## How it works 1. Create an `AGSMapView` object. -2. Create and load a `AGSUtilityNetwork` with a feature service URL. -3. Create an `AGSMap` object that contains `AGSFeatureLayer`(s) that are part of this utility network. -4. Create a default starting location from a given asset type and global ID. -5. Add an `AGSGraphicsOverlay` with an `AGSGraphic` that represents this starting location. -6. Populate the choice list for the filter barriers from the `categories` property of `AGSUtilityNetworkDefinition`. -7. Get a default `AGSUtilityTraceConfiguration` from a given tier in a domain network. Set its `filter` property with an `AGSUtilityTraceFilter` object. -8. When "Trace" is tapped, +2. Create and load an `AGSServiceGeodatabase` with a feature service URL and get tables with their layer IDs. +3. Create an `AGSMap` object that contains `AGSFeatureLayer`(s) created from the service geodatabase's tables. +4. Create and load an `AGSUtilityNetwork` with the same feature service URL and map. +5. Create a default starting location from a given asset type and global ID. +6. Add an `AGSGraphicsOverlay` with an `AGSGraphic` that represents this starting location. +7. Populate the choice list for the filter barriers from the `categories` property of `AGSUtilityNetworkDefinition`. +8. Get a default `AGSUtilityTraceConfiguration` from a given tier in a domain network. Set its `filter` property with an `AGSUtilityTraceFilter` object. +9. When "Trace" is tapped, * Create a new `AGSUtilityCategoryComparison` with the selected category and `AGSUtilityCategoryComparisonOperator.exists`. * Assign this condition to `AGSUtilityTraceFilter.barriers` from the default configuration from step 7. * Update the configuration's `includeIsolatedFeatures` property. * Create an `AGSUtilityTraceParameters` object with `AGSUtilityTraceType.isolation` and default starting location from step 4. * Set this configuration to the parameters' `traceConfiguration` property. * Run `AGSUtilityNetwork.trace(with:completion:)` with the specified parameters. -9. Group the `AGSUtilityElementTraceResult.elements` by their `networkSource.name`. -10. For every `AGSFeatureLayer` in this map with trace result elements, select features by converting `AGSUtilityElement`(s) to `AGSArcGISFeature`(s) using `AGSUtilityNetwork.features(for:completion:)`. +10. Group the `AGSUtilityElementTraceResult.elements` by their `networkSource.name`. +11. For every `AGSFeatureLayer` in this map with trace result elements, select features by converting `AGSUtilityElement`(s) to `AGSArcGISFeature`(s) using `AGSUtilityNetwork.features(for:completion:)`. ## Relevant API +* AGSServiceGeodatabase * AGSUtilityCategory * AGSUtilityCategoryComparison * AGSUtilityCategoryComparisonOperator diff --git a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.metadata.json index ea32115fc..9fa732bfc 100644 --- a/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Perform valve isolation trace/README.metadata.json @@ -14,6 +14,7 @@ "trace configuration", "trace filter", "utility network", + "AGSServiceGeodatabase", "AGSUtilityCategory", "AGSUtilityCategoryComparison", "AGSUtilityCategoryComparisonOperator", @@ -30,6 +31,7 @@ ], "redirect_from": [], "relevant_apis": [ + "AGSServiceGeodatabase", "AGSUtilityCategory", "AGSUtilityCategoryComparison", "AGSUtilityCategoryComparisonOperator", 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 b63c10a6b..c30ac5c0b 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 @@ -15,23 +15,25 @@ Tap on one or more features while "Start" or "Barrier" is selected. When a junct ## How it works 1. Create an `AGSMapView` and listen for `didTap` events on the `AGSGeoViewTouchDelegate`. -2. Create an `AGSMap` that contains `AGSFeatureLayer`(s) that are part of a utility network. -3. Create and load an `AGSUtilityNetwork` with the same feature service URL and map. -4. Add an `AGSGraphicsOverlay` with symbology that distinguishes starting locations from barriers. -5. Identify tapped features on the map and add an `AGSGraphic` that represents its purpose (starting point or barrier) at the tapped location. -6. Create an `AGSUtilityElement` for the identified feature. -7. Determine the type of the identified feature using `AGSUtilityNetworkSource.sourceType`. -8. If the type is `junction`, display a terminal picker when more than one terminal is found and create an `AGSUtilityElement` using the selected terminal, or the single terminal if there is only one. -9. If the type is `edge`, create an `AGSUtilityElement` from the identified feature and compute how far along the edge the user tapped using `class AGSGeometryEngine.fraction(alongLine:to:tolerance:)`. -10. Add this `AGSUtilityElement` to a collection of starting locations or barriers. -11. Create `AGSUtilityTraceParameters` with the selected trace type along with the collected starting locations and barriers (if applicable). -12. Set the `AGSUtilityTraceConfiguration` with the utility tier's `traceConfiguration` property. -13. Run `AGSUtilityNetwork.trace(with:completion:)` with the specified starting points and (optionally) barriers. -14. Group the `AGSUtilityElementTraceResult.elements` by their `networkSource.name`. -15. For every `AGSFeatureLayer` in this map with trace result elements, select features by converting `AGSUtilityElement`(s) to `AGSArcGISFeature`(s) using `AGSUtilityNetwork.features(for:completion:)`. +2. Create and load an `AGSServiceGeodatabase` with a feature service URL and get tables with their layer IDs. +3. Create an `AGSMap` object that contains `AGSFeatureLayer`(s) created from the service geodatabase's tables. +4. Create and load an `AGSUtilityNetwork` with the same feature service URL and map. +5. Add an `AGSGraphicsOverlay` with symbology that distinguishes starting locations from barriers. +6. Identify tapped features on the map and add an `AGSGraphic` that represents its purpose (starting point or barrier) at the tapped location. +7. Create an `AGSUtilityElement` for the identified feature. +8. Determine the type of the identified feature using `AGSUtilityNetworkSource.sourceType`. +9. If the type is `junction`, display a terminal picker when more than one terminal is found and create an `AGSUtilityElement` using the selected terminal, or the single terminal if there is only one. +10. If the type is `edge`, create an `AGSUtilityElement` from the identified feature and compute how far along the edge the user tapped using `class AGSGeometryEngine.fraction(alongLine:to:tolerance:)`. +11. Add this `AGSUtilityElement` to a collection of starting locations or barriers. +12. Create `AGSUtilityTraceParameters` with the selected trace type along with the collected starting locations and barriers (if applicable). +13. Set the `AGSUtilityTraceConfiguration` with the utility tier's `traceConfiguration` property. +14. Run `AGSUtilityNetwork.trace(with:completion:)` with the specified starting points and (optionally) barriers. +15. Group the `AGSUtilityElementTraceResult.elements` by their `networkSource.name`. +16. For every `AGSFeatureLayer` in this map with trace result elements, select features by converting `AGSUtilityElement`(s) to `AGSArcGISFeature`(s) using `AGSUtilityNetwork.features(for:completion:)`. ## Relevant API +* AGSServiceGeodatabase * AGSUtilityAssetType * AGSUtilityDomainNetwork * AGSUtilityElement diff --git a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.metadata.json b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.metadata.json index db09a7f89..471f51a7c 100644 --- a/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.metadata.json +++ b/arcgis-ios-sdk-samples/Utility network/Trace utility network/README.metadata.json @@ -15,6 +15,7 @@ "upstream trace", "utility network", "validate consistency", + "AGSServiceGeodatabase", "AGSUtilityAssetType", "AGSUtilityDomainNetwork", "AGSUtilityElement", @@ -33,6 +34,7 @@ ], "redirect_from": [], "relevant_apis": [ + "AGSServiceGeodatabase", "AGSUtilityAssetType", "AGSUtilityDomainNetwork", "AGSUtilityElement", diff --git a/arcgis-ios-sdk-samples/Utility network/Trace utility network/TraceUtilityNetworkViewController.swift b/arcgis-ios-sdk-samples/Utility network/Trace utility network/TraceUtilityNetworkViewController.swift index 16bbe303a..f5bac09c5 100644 --- a/arcgis-ios-sdk-samples/Utility network/Trace utility network/TraceUtilityNetworkViewController.swift +++ b/arcgis-ios-sdk-samples/Utility network/Trace utility network/TraceUtilityNetworkViewController.swift @@ -25,44 +25,19 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega @IBOutlet weak var statusLabel: UILabel! @IBOutlet weak var modeControl: UISegmentedControl! - private let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! - - // Create electrical distribution line layer ./3 and electrical device layer ./0. - private var layers: [AGSFeatureLayer] { - return [3, 0].map { - let featureTable = AGSServiceFeatureTable(url: featureServiceURL.appendingPathComponent("\($0)")) - let layer = AGSFeatureLayer(featureTable: featureTable) - if $0 == 3 { - // Define a solid line for medium voltage lines and a dashed line for low voltage lines. - let darkCyan = UIColor(red: 0, green: 0.55, blue: 0.55, alpha: 1) - let mediumVoltageValue = AGSUniqueValue( - description: "N/A", - label: "Medium voltage", - symbol: AGSSimpleLineSymbol(style: .solid, color: darkCyan, width: 3), - values: [5] - ) - let lowVoltageValue = AGSUniqueValue( - description: "N/A", - label: "Low voltage", - symbol: AGSSimpleLineSymbol(style: .dash, color: darkCyan, width: 3), - values: [3] - ) - layer.renderer = AGSUniqueValueRenderer( - fieldNames: ["ASSETGROUP"], - uniqueValues: [mediumVoltageValue, lowVoltageValue], - defaultLabel: "", - defaultSymbol: AGSSimpleLineSymbol() - ) - } - return layer - } - } + private static let featureServiceURL = URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer")! private let map: AGSMap - private let utilityNetwork: AGSUtilityNetwork + private let serviceGeodatabase = AGSServiceGeodatabase(url: featureServiceURL) + private let utilityNetwork = AGSUtilityNetwork(url: featureServiceURL) private var utilityTier: AGSUtilityTier? private var traceType = (name: "Connected", type: AGSUtilityTraceType.connected) private var traceParameters = AGSUtilityTraceParameters(traceType: .connected, startingLocations: []) + // Create electrical distribution line layer ./3 and electrical device layer ./0. + private let featureLayerURLs = [ + featureServiceURL.appendingPathComponent("3"), + featureServiceURL.appendingPathComponent("0") + ] private let parametersOverlay: AGSGraphicsOverlay = { let barrierPointSymbol = AGSSimpleMarkerSymbol(style: .X, color: .red, size: 20) @@ -83,16 +58,49 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega return overlay }() - // MARK: Initialize map and Utility Network + // MARK: Initialize map, utility network, and service geodatabase required init?(coder aDecoder: NSCoder) { // Create the map map = AGSMap(basemapStyle: .arcGISStreetsNight) - // Create the utility network, referencing the map. - utilityNetwork = AGSUtilityNetwork(url: featureServiceURL, map: map) - super.init(coder: aDecoder) - // Add the utility network feature layers to the map for display. - map.operationalLayers.addObjects(from: layers) + // Add the utility network to the map's array of utility networks. + map.utilityNetworks.add(utilityNetwork) + // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. + utilityNetwork.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") + super.init(coder: aDecoder) + // Load the service geodatabase. + serviceGeodatabase.load { [weak self] _ in + guard let self = self else { return } + let layers = self.featureLayerURLs.map { url -> AGSFeatureLayer in + let featureTable = AGSServiceFeatureTable(url: url) + let layer = AGSFeatureLayer(featureTable: featureTable) + if featureTable.serviceLayerID == 3 { + // Define a solid line for medium voltage lines and a dashed line for low voltage lines. + let darkCyan = UIColor(red: 0, green: 0.55, blue: 0.55, alpha: 1) + let mediumVoltageValue = AGSUniqueValue( + description: "N/A", + label: "Medium voltage", + symbol: AGSSimpleLineSymbol(style: .solid, color: darkCyan, width: 3), + values: [5] + ) + let lowVoltageValue = AGSUniqueValue( + description: "N/A", + label: "Low voltage", + symbol: AGSSimpleLineSymbol(style: .dash, color: darkCyan, width: 3), + values: [3] + ) + layer.renderer = AGSUniqueValueRenderer( + fieldNames: ["ASSETGROUP"], + uniqueValues: [mediumVoltageValue, lowVoltageValue], + defaultLabel: "", + defaultSymbol: AGSSimpleLineSymbol() + ) + } + return layer + } + // Add the utility network feature layers to the map for display. + self.map.operationalLayers.addObjects(from: layers) + } } // MARK: Initialize user interface @@ -120,8 +128,6 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega // Set the selection color for features in the map view. mapView.selectionProperties = AGSSelectionProperties(color: .yellow) - // NOTE: Never hardcode login information in a production application. This is done solely for the sake of the sample. - utilityNetwork.credential = AGSCredential(user: "viewer01", password: "I68VGU^nMurF") // Load the Utility Network to be ready for us to run a trace against it. setStatus(message: "Loading Utility Network…") utilityNetwork.load { [weak self] error in @@ -227,7 +233,7 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega // MARK: Perform Trace @IBAction func traceNetwork(_ sender: Any) { - SVProgressHUD.show(withStatus: "Running \(traceType.name.lowercased()) trace…") + UIApplication.shared.showProgressHUD(message: "Running \(traceType.name.lowercased()) trace…") let parameters = AGSUtilityTraceParameters(traceType: traceType.type, startingLocations: traceParameters.startingLocations) parameters.barriers.append(contentsOf: traceParameters.barriers) @@ -237,7 +243,7 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega utilityNetwork.trace(with: parameters) { [weak self] (traceResult, error) in if let error = error { self?.setStatus(message: "Trace failed.") - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() self?.presentAlert(error: error) return } @@ -247,13 +253,13 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega guard let elementTraceResult = traceResult?.first as? AGSUtilityElementTraceResult, !elementTraceResult.elements.isEmpty else { self.setStatus(message: "Trace completed with no output.") - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() return } self.clearSelection() - SVProgressHUD.show(withStatus: "Trace completed. Selecting features…") + UIApplication.shared.showProgressHUD(message: "Trace completed. Selecting features…") let groupedElements = Dictionary(grouping: elementTraceResult.elements) { $0.networkSource.name } @@ -281,7 +287,7 @@ class TraceUtilityNetworkViewController: UIViewController, AGSGeoViewTouchDelega selectionGroup.notify(queue: .main) { [weak self] in self?.setStatus(message: "Trace completed.") - SVProgressHUD.dismiss() + UIApplication.shared.hideProgressHUD() } } } diff --git a/arcgis-runtime-toolkit-ios b/arcgis-runtime-toolkit-ios deleted file mode 160000 index 5f1e65c77..000000000 --- a/arcgis-runtime-toolkit-ios +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f1e65c772d1269dcdbc6cdfecbcd2e0adbd6a57 diff --git a/podfile b/podfile index 21fcd9b03..6b09553fc 100644 --- a/podfile +++ b/podfile @@ -1,5 +1,5 @@ -platform :ios, '12.0' +platform :ios, '13.0' target 'ArcGIS Runtime SDK Samples' do use_frameworks! - pod 'ArcGIS-Runtime-Toolkit-iOS', '~> 100.10' + pod 'ArcGIS-Runtime-Toolkit-iOS', '~> 100.11' end \ No newline at end of file