Skip to content
This repository was archived by the owner on Jan 6, 2023. It is now read-only.
31 changes: 27 additions & 4 deletions arcgis-ios-sdk-samples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
00ADC3D12464DD3600A3B88D /* IdentifyRasterCellViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00ADC3D02464DD3600A3B88D /* IdentifyRasterCellViewController.swift */; };
00ADC3D22464DDA200A3B88D /* IdentifyRasterCellViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00ADC3D02464DD3600A3B88D /* IdentifyRasterCellViewController.swift */; };
00BA068525311B0D0039EF4D /* hydrography in Resources */ = {isa = PBXBuildFile; fileRef = 00BA068325311B0D0039EF4D /* hydrography */; settings = {ASSET_TAGS = (Hydrography, ); }; };
00BE7B38275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */; };
00BE7B3E2764274C0012CE95 /* BrowseBuildingFloors.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 00BE7B3D2764274C0012CE95 /* BrowseBuildingFloors.storyboard */; };
00BE7B402764275D0012CE95 /* BrowseBuildingFloorsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BE7B3F2764275D0012CE95 /* BrowseBuildingFloorsViewController.swift */; };
00BE7B4127642A6C0012CE95 /* BrowseBuildingFloorsViewController.swift in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00BE7B3F2764275D0012CE95 /* BrowseBuildingFloorsViewController.swift */; };
Expand Down Expand Up @@ -1898,6 +1899,7 @@
buildActionMask = 2147483647;
files = (
006A786A262F9F15001D2A5E /* ArcGISToolkit in Frameworks */,
00BE7B38275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -4773,6 +4775,7 @@
name = "ArcGIS Runtime SDK Samples";
packageProductDependencies = (
006A7869262F9F15001D2A5E /* ArcGISToolkit */,
00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */,
);
productName = "arcgis-ios-sdk-samples";
productReference = 3E23A9E01AFC28F6002E2214 /* ArcGIS Runtime SDK Samples.app */;
Expand Down Expand Up @@ -4876,6 +4879,7 @@
mainGroup = 3E23A9D71AFC28F6002E2214;
packageReferences = (
006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */,
00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
);
productRefGroup = 3E23A9E11AFC28F6002E2214 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -5759,8 +5763,11 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 100.13.0;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
);
PRODUCT_BUNDLE_IDENTIFIER = com.esri.iOSSamples;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -5788,8 +5795,11 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 100.13.0;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.esri.arcgis-ios-sdk-samples";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
);
PRODUCT_BUNDLE_IDENTIFIER = com.esri.iOSSamples;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -5897,6 +5907,14 @@
minimumVersion = 100.13.0;
};
};
00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 8.10.0;
};
};
Comment on lines +5995 to +6002
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never used Firebase before. What impact does adding this dependency have on app size (how large is the Firebase framework)? Also, will we need to change the App Privacy section of our App Store page?

For what it is worth, I generally am not in favor of adding third part dependencies unless there is an extremely compelling reason to do so. Each dependency, especially one like this that executes code even before that app is useable by the user, is a failure point. Remember a while back when a bunch of prominent apps stopped working for a while because they used a popular third party analytics framework that had a problem? That is the power that dependencies like this hold. In my opinion, it isn't worth it. But that's up to you and the samples team to decide.

Copy link
Collaborator Author

@yo1995 yo1995 Mar 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • app size
    The impact is quite minimum. The previous version (100.13.0.1) of sample viewer app is ~85 MB (can't remember exact number), and the current version (100.13.0.2) is 87 MB, according to App Store on iPhone 11.
  • App Privacy section
    I've included usage data (select sample, category, and source code view) and search history (search bar) policies, prior to the release.
  • third party dependencies
    I agree. I also tried to avoid using 3rd party dependencies in my personal project.
    We researched a few options: Google Analytics, Amazon Pinpoint, Adobe Analytics, and building an AWS based in house solution. Eventually Trevor decided GA is the easiest way to go for now, as we wanted to use it as an experiment to see what data we can get. In the future we may decide to move to other solutions or remove GA dependency.

/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand All @@ -5905,6 +5923,11 @@
package = 006A7868262F9F15001D2A5E /* XCRemoteSwiftPackageReference "arcgis-runtime-toolkit-ios" */;
productName = ArcGISToolkit;
};
00BE7B37275AEFD60012CE95 /* FirebaseAnalyticsWithoutAdIdSupport */ = {
isa = XCSwiftPackageProductDependency;
package = 00BE7B36275AEFD60012CE95 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseAnalyticsWithoutAdIdSupport;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 3E23A9D81AFC28F6002E2214 /* Project object */;
Expand Down
14 changes: 14 additions & 0 deletions arcgis-ios-sdk-samples/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import UIKit
import ArcGIS
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
Expand Down Expand Up @@ -48,6 +49,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
// Enable/disable touches based on settings.
self.setTouchPref()

// Set up Google Analytics 4.
self.setGoogleAnalyticsPref()

// Set license key and/or API key.
application.license()

Expand Down Expand Up @@ -91,6 +95,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
}
}

// MARK: - Google Analytics settings

func setGoogleAnalyticsPref() {
// Enable/disable GA based on settings.
let disableGoogleAnalytics = UserDefaults.standard.bool(forKey: "disableGoogleAnalytics")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is due to an iOS limitation, see: https://stackoverflow.com/questions/36253998

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't an iOS limitation but rather a misunderstanding of the User Defaults API. It has been a while since I've used it, but if I remember quickly, default values must be registered using UserDefaults.register(defaults:). Also, be aware that the setting can change while the app is active, so the setting should be observed for changes as well. In fact, using the initial option, the observation itself can be what enables and disables analytics exclusively.

if !disableGoogleAnalytics {
FirebaseApp.configure()
}
}

// MARK: - Appearance modification

func modifyAppearance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

import UIKit
import Firebase

class ContentCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
@IBOutlet private var collectionViewFlowLayout: UICollectionViewFlowLayout!
Expand Down Expand Up @@ -96,6 +97,12 @@ class ContentCollectionViewController: UICollectionViewController, UICollectionV
let controller = storyboard!.instantiateViewController(withIdentifier: "ContentTableViewController") as! ContentTableViewController
controller.allSamples = category.samples
controller.title = category.name

// Google Analytics select category event.
Analytics.logEvent("select_category", parameters: [
AnalyticsParameterContentType: category.name
])

show(controller, sender: self)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

import UIKit
import Firebase

class ContentTableViewController: UITableViewController {
/// The samples to display in the table. Searching adjusts this value
Expand All @@ -29,7 +30,7 @@ class ContentTableViewController: UITableViewController {
displayedSamples = allSamples
}
}

var searchEngine: SampleSearchEngine?

private var expandedRowIndexPaths: Set<IndexPath> = []
Expand Down Expand Up @@ -71,6 +72,11 @@ class ContentTableViewController: UITableViewController {
/// Responds to the selected sample being changed.
private func selectedSampleDidChange() {
if let sample = selectedSample {
// Google Analytics select sample event.
Analytics.logEvent("select_sample", parameters: [
AnalyticsParameterContentType: sample.name
])

let indexPathForSample = indexPath(for: sample)
if tableView.indexPathForSelectedRow != indexPathForSample {
tableView.selectRow(at: indexPathForSample, animated: true, scrollPosition: .top)
Expand Down Expand Up @@ -108,13 +114,13 @@ class ContentTableViewController: UITableViewController {
}
}
}

// MARK: - UITableViewDataSource

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return displayedSamples.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sample = displayedSamples[indexPath.row]

Expand Down Expand Up @@ -189,7 +195,18 @@ class ContentTableViewController: UITableViewController {

// must use the presenting controller when opening from search results or else splitViewController will be nil
let presentingController: UIViewController? = searchEngine != nil ? presentingViewController : self


// If the sample is selected from search results, log the search term.
if let searchController = presentingViewController?.navigationItem.searchController,
searchController.isActive,
let searchTerm = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!searchTerm.isEmpty {
// Google Analytics search event.
Analytics.logEvent(AnalyticsEventSearch, parameters: [
AnalyticsParameterSearchTerm: searchTerm
])
}

let navController = UINavigationController(rootViewController: controller)

// don't use large titles on samples
Expand Down Expand Up @@ -242,8 +259,8 @@ extension ContentTableViewController: UISearchResultsUpdating {
expandedRowIndexPaths.removeAll()

if searchController.isActive,
let query = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!query.isEmpty {
let query = searchController.searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!query.isEmpty {
displayedSamples = searchEngine.sortedSamples(matching: query)
} else {
displayedSamples = allSamples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import UIKit
import WebKit
import Firebase

class SourceCodeViewController: UIViewController, UIAdaptivePresentationControllerDelegate {
/// The view to which the web view is added.
Expand Down Expand Up @@ -56,6 +57,11 @@ class SourceCodeViewController: UIViewController, UIAdaptivePresentationControll
setupToolbarTitle(filename, arrowPointingDown: true)
let htmlString = htmlStringForContent(content)
webView.loadHTMLString(htmlString, baseURL: URL(fileURLWithPath: Bundle.main.bundlePath))

// Google Analytics select code file event.
Analytics.logEvent("select_sourcefile", parameters: [
AnalyticsParameterContentType: filename
])
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@
<key>DefaultValue</key>
<false/>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Disable Google Analytics</string>
<key>Key</key>
<string>disableGoogleAnalytics</string>
<key>DefaultValue</key>
<false/>
</dict>
</array>
</dict>
</plist>
2 changes: 2 additions & 0 deletions arcgis-ios-sdk-samples/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED</key>
<false/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
Expand Down