diff --git a/.github/GoogleService-Info-CI.plist b/.github/GoogleService-Info-CI.plist
new file mode 100644
index 00000000..5d96fe50
--- /dev/null
+++ b/.github/GoogleService-Info-CI.plist
@@ -0,0 +1,38 @@
+
+
+
+
+ CLIENT_ID
+ 000000000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.000000000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ ANDROID_CLIENT_ID
+ 000000000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com
+ API_KEY
+ AAAAAAAAAAA_AAAAA_AAAAAAAAAAAAAAAAAAAAA
+ GCM_SENDER_ID
+ 000000000000
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ com.google.firebase.sample.build
+ PROJECT_ID
+ aaaaaa-aaa-aaaaa
+ STORAGE_BUCKET
+ aaaaaa-aaa-aaaaa.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:000000000000:ios:aaaaaaaaaaaaaaaa
+ DATABASE_URL
+ https://aaaaaa-aaa-aaaaa.firebaseio.com
+
+
\ No newline at end of file
diff --git a/.github/workflows/appcheck.yml b/.github/workflows/appcheck.yml
new file mode 100644
index 00000000..e1db0f5a
--- /dev/null
+++ b/.github/workflows/appcheck.yml
@@ -0,0 +1,41 @@
+on:
+ pull_request:
+ paths:
+ - 'appcheck/**'
+ - '.github/workflows/appcheck.yml'
+name: App Check
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd appcheck
+ xcodebuild -project AppCheckSnippets.xcodeproj clean build -scheme AppCheckSnippetsSwift -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ cd appcheck
+ xcodebuild -project AppCheckSnippets.xcodeproj clean build -scheme AppCheckSnippetsObjC -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml
new file mode 100644
index 00000000..644f018c
--- /dev/null
+++ b/.github/workflows/core.yml
@@ -0,0 +1,25 @@
+on:
+ pull_request:
+ paths:
+ - 'firoptions/**'
+ - '.github/workflows/core.yml'
+name: Analytics + Core
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cp .github/GoogleService-Info-CI.plist firoptions/FiroptionConfiguration/GoogleService-Info.plist
+ cd firoptions
+ xcodebuild -project FiroptionConfiguration.xcodeproj clean build -scheme FiroptionConfiguration -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/crashlytics.yml b/.github/workflows/crashlytics.yml
new file mode 100644
index 00000000..4c3b982e
--- /dev/null
+++ b/.github/workflows/crashlytics.yml
@@ -0,0 +1,41 @@
+on:
+ pull_request:
+ paths:
+ - 'crashlytics/**'
+ - '.github/workflows/crashlytics.yml'
+name: Crashlytics
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd crashlytics
+ xcodebuild -project CrashlyticsExample.xcodeproj clean build -scheme CrashlyticsExampleSwift -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ cd crashlytics
+ xcodebuild -project CrashlyticsExample.xcodeproj clean build -scheme CrashlyticsExample -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/database.yml b/.github/workflows/database.yml
new file mode 100644
index 00000000..fe3f424c
--- /dev/null
+++ b/.github/workflows/database.yml
@@ -0,0 +1,24 @@
+on:
+ pull_request:
+ paths:
+ - 'database/**'
+ - '.github/workflows/database.yml'
+name: Database
+jobs:
+ swift-build:
+ name: Build combined snippets
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build snippets
+ run: |
+ cd database
+ xcodebuild -project DatabaseReference.xcodeproj clean build -scheme DatabaseReference -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/firestore.yml b/.github/workflows/firestore.yml
new file mode 100644
index 00000000..37d9f810
--- /dev/null
+++ b/.github/workflows/firestore.yml
@@ -0,0 +1,43 @@
+on:
+ pull_request:
+ paths:
+ - 'firestore/**'
+ - '.github/workflows/firestore.yml'
+name: Firestore
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cp .github/GoogleService-Info-CI.plist firestore/swift/firestore-smoketest/GoogleService-Info.plist
+ cd firestore/swift
+ xcodebuild -project firestore-smoketest.xcodeproj clean build -scheme firestore-smoketest -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ cp .github/GoogleService-Info-CI.plist firestore/objc/GoogleService-Info.plist
+ cd firestore/objc
+ xcodebuild -project firestore-smoketest-objc.xcodeproj clean build -scheme firestore-smoketest-objc -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/functions.yml b/.github/workflows/functions.yml
new file mode 100644
index 00000000..fe0cd5e3
--- /dev/null
+++ b/.github/workflows/functions.yml
@@ -0,0 +1,41 @@
+on:
+ pull_request:
+ paths:
+ - 'functions/**'
+ - '.github/workflows/functions.yml'
+name: Functions
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd functions
+ xcodebuild -project FunctionsExample.xcodeproj clean build -scheme FunctionsExampleSwift -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ cd functions
+ xcodebuild -project FunctionsExample.xcodeproj clean build -scheme FunctionsExample -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/installations.yml b/.github/workflows/installations.yml
new file mode 100644
index 00000000..8286a823
--- /dev/null
+++ b/.github/workflows/installations.yml
@@ -0,0 +1,24 @@
+on:
+ pull_request:
+ paths:
+ - 'installations/**'
+ - '.github/workflows/installations.yml'
+name: Installations
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd installations/
+ xcodebuild -project InstallationsSnippets.xcodeproj clean build -scheme InstallationsSnippets -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
\ No newline at end of file
diff --git a/.github/workflows/ml-functions.yml b/.github/workflows/ml-functions.yml
new file mode 100644
index 00000000..f28a921d
--- /dev/null
+++ b/.github/workflows/ml-functions.yml
@@ -0,0 +1,41 @@
+on:
+ pull_request:
+ paths:
+ - 'ml-functions/**'
+ - '.github/workflows/ml-functions.yml'
+name: Functions (ML)
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd ml-functions
+ xcodebuild -project MLFunctionsExample.xcodeproj clean build -scheme MLFunctionsExampleSwift -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ cd ml-functions
+ xcodebuild -project MLFunctionsExample.xcodeproj clean build -scheme MLFunctionsExample -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/storage.yml b/.github/workflows/storage.yml
new file mode 100644
index 00000000..73949ab2
--- /dev/null
+++ b/.github/workflows/storage.yml
@@ -0,0 +1,43 @@
+on:
+ pull_request:
+ paths:
+ - 'storage/**'
+ - '.github/workflows/storage.yml'
+name: Storage
+jobs:
+ swift-build:
+ name: Swift build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ sudo xcode-select -switch /Applications/Xcode_16.1.app/Contents/Developer
+ cd storage
+ xcodebuild -project StorageReference.xcodeproj clean build -scheme StorageReferenceSwift -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
+ objc-build:
+ name: ObjC build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 16']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build ObjC snippets
+ run: |
+ sudo xcode-select -switch /Applications/Xcode_16.1.app/Contents/Developer
+ cd storage
+ xcodebuild -project StorageReference.xcodeproj clean build -scheme StorageReference -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.github/workflows/vertexai.yml b/.github/workflows/vertexai.yml
new file mode 100644
index 00000000..30b61ab6
--- /dev/null
+++ b/.github/workflows/vertexai.yml
@@ -0,0 +1,24 @@
+on:
+ pull_request:
+ paths:
+ - 'vertexai/**'
+ - '.github/workflows/vertexai.yml'
+name: VertexAI
+jobs:
+ snippets-build:
+ name: snippets build
+ runs-on: macOS-latest
+ strategy:
+ matrix:
+ destination: ['platform=iOS Simulator,OS=latest,name=iPhone 15', 'platform=OS X']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Install deps
+ run: brew install xcbeautify
+ - name: Build Swift snippets
+ run: |
+ cd vertexai
+ xcodebuild -project VertexAISnippets.xcodeproj -scheme VertexAISnippets clean build -destination "${destination}" CODE_SIGNING_REQUIRED=NO | xcbeautify --renderer github-actions
+ env:
+ destination: ${{ matrix.destination }}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2cf08328..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-osx_image: xcode10
-language: objective-c
-
-cache:
- - bundler
- - cocoapods
-
-before_install:
- - gem install xcpretty
- - pod install --repo-update
-
-script: ./build.sh
diff --git a/appcheck/AppCheckSnippets.xcodeproj/project.pbxproj b/appcheck/AppCheckSnippets.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..319930a4
--- /dev/null
+++ b/appcheck/AppCheckSnippets.xcodeproj/project.pbxproj
@@ -0,0 +1,660 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 4265C38C26AF71E100BD1DB2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C38B26AF71E100BD1DB2 /* AppDelegate.m */; };
+ 4265C38F26AF71E100BD1DB2 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C38E26AF71E100BD1DB2 /* SceneDelegate.m */; };
+ 4265C39226AF71E100BD1DB2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C39126AF71E100BD1DB2 /* ViewController.m */; };
+ 4265C39526AF71E100BD1DB2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4265C39326AF71E100BD1DB2 /* Main.storyboard */; };
+ 4265C39726AF71E300BD1DB2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4265C39626AF71E300BD1DB2 /* Assets.xcassets */; };
+ 4265C39A26AF71E300BD1DB2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4265C39826AF71E300BD1DB2 /* LaunchScreen.storyboard */; };
+ 4265C39D26AF71E300BD1DB2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C39C26AF71E300BD1DB2 /* main.m */; };
+ 4265C3A826AF723800BD1DB2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3A726AF723800BD1DB2 /* AppDelegate.swift */; };
+ 4265C3AA26AF723800BD1DB2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3A926AF723800BD1DB2 /* SceneDelegate.swift */; };
+ 4265C3AC26AF723800BD1DB2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3AB26AF723800BD1DB2 /* ViewController.swift */; };
+ 4265C3AF26AF723800BD1DB2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4265C3AD26AF723800BD1DB2 /* Main.storyboard */; };
+ 4265C3B126AF723900BD1DB2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4265C3B026AF723900BD1DB2 /* Assets.xcassets */; };
+ 4265C3B426AF723900BD1DB2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4265C3B226AF723900BD1DB2 /* LaunchScreen.storyboard */; };
+ 4265C3BA26AF74F800BD1DB2 /* AppAttestProviderFactories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3B926AF74F800BD1DB2 /* AppAttestProviderFactories.swift */; };
+ 4265C3BC26AF775A00BD1DB2 /* AppAttestProviderFactories.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3BB26AF775A00BD1DB2 /* AppAttestProviderFactories.m */; };
+ 4265C3BE26AF7A6600BD1DB2 /* YourCustomAppCheckProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3BD26AF7A6600BD1DB2 /* YourCustomAppCheckProvider.swift */; };
+ 4265C3C026AF7A7E00BD1DB2 /* YourCustomAppCheckProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4265C3BF26AF7A7E00BD1DB2 /* YourCustomAppCheckProvider.m */; };
+ 8D7726082D2874A100537A0B /* FirebaseAppCheck in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726072D2874A100537A0B /* FirebaseAppCheck */; };
+ 8D77260A2D2874A100537A0B /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726092D2874A100537A0B /* FirebaseCore */; };
+ 8D77260D2D2874BA00537A0B /* FirebaseAppCheck in Frameworks */ = {isa = PBXBuildFile; productRef = 8D77260C2D2874BA00537A0B /* FirebaseAppCheck */; };
+ 8D77260F2D2874BA00537A0B /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D77260E2D2874BA00537A0B /* FirebaseCore */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 4265C38726AF71E100BD1DB2 /* AppCheckSnippetsObjC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppCheckSnippetsObjC.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4265C38A26AF71E100BD1DB2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 4265C38B26AF71E100BD1DB2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 4265C38D26AF71E100BD1DB2 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; };
+ 4265C38E26AF71E100BD1DB2 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; };
+ 4265C39026AF71E100BD1DB2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
+ 4265C39126AF71E100BD1DB2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
+ 4265C39426AF71E100BD1DB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 4265C39626AF71E300BD1DB2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 4265C39926AF71E300BD1DB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 4265C39B26AF71E300BD1DB2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 4265C39C26AF71E300BD1DB2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 4265C3A526AF723800BD1DB2 /* AppCheckSnippetsSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppCheckSnippetsSwift.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4265C3A726AF723800BD1DB2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 4265C3A926AF723800BD1DB2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
+ 4265C3AB26AF723800BD1DB2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 4265C3AE26AF723800BD1DB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 4265C3B026AF723900BD1DB2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 4265C3B326AF723900BD1DB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 4265C3B526AF723900BD1DB2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 4265C3B926AF74F800BD1DB2 /* AppAttestProviderFactories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAttestProviderFactories.swift; sourceTree = ""; };
+ 4265C3BB26AF775A00BD1DB2 /* AppAttestProviderFactories.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppAttestProviderFactories.m; sourceTree = ""; };
+ 4265C3BD26AF7A6600BD1DB2 /* YourCustomAppCheckProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YourCustomAppCheckProvider.swift; sourceTree = ""; };
+ 4265C3BF26AF7A7E00BD1DB2 /* YourCustomAppCheckProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YourCustomAppCheckProvider.m; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4265C38426AF71E100BD1DB2 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D77260A2D2874A100537A0B /* FirebaseCore in Frameworks */,
+ 8D7726082D2874A100537A0B /* FirebaseAppCheck in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4265C3A226AF723800BD1DB2 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D77260F2D2874BA00537A0B /* FirebaseCore in Frameworks */,
+ 8D77260D2D2874BA00537A0B /* FirebaseAppCheck in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4265C38826AF71E100BD1DB2 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4265C38726AF71E100BD1DB2 /* AppCheckSnippetsObjC.app */,
+ 4265C3A526AF723800BD1DB2 /* AppCheckSnippetsSwift.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 4265C38926AF71E100BD1DB2 /* AppCheckSnippetsObjC */ = {
+ isa = PBXGroup;
+ children = (
+ 4265C38A26AF71E100BD1DB2 /* AppDelegate.h */,
+ 4265C38B26AF71E100BD1DB2 /* AppDelegate.m */,
+ 4265C38D26AF71E100BD1DB2 /* SceneDelegate.h */,
+ 4265C38E26AF71E100BD1DB2 /* SceneDelegate.m */,
+ 4265C39026AF71E100BD1DB2 /* ViewController.h */,
+ 4265C39126AF71E100BD1DB2 /* ViewController.m */,
+ 4265C39326AF71E100BD1DB2 /* Main.storyboard */,
+ 4265C39626AF71E300BD1DB2 /* Assets.xcassets */,
+ 4265C39826AF71E300BD1DB2 /* LaunchScreen.storyboard */,
+ 4265C39B26AF71E300BD1DB2 /* Info.plist */,
+ 4265C39C26AF71E300BD1DB2 /* main.m */,
+ 4265C3BB26AF775A00BD1DB2 /* AppAttestProviderFactories.m */,
+ 4265C3BF26AF7A7E00BD1DB2 /* YourCustomAppCheckProvider.m */,
+ );
+ path = AppCheckSnippetsObjC;
+ sourceTree = "";
+ };
+ 4265C3A626AF723800BD1DB2 /* AppCheckSnippetsSwift */ = {
+ isa = PBXGroup;
+ children = (
+ 4265C3A726AF723800BD1DB2 /* AppDelegate.swift */,
+ 4265C3A926AF723800BD1DB2 /* SceneDelegate.swift */,
+ 4265C3AB26AF723800BD1DB2 /* ViewController.swift */,
+ 4265C3AD26AF723800BD1DB2 /* Main.storyboard */,
+ 4265C3B026AF723900BD1DB2 /* Assets.xcassets */,
+ 4265C3B226AF723900BD1DB2 /* LaunchScreen.storyboard */,
+ 4265C3B526AF723900BD1DB2 /* Info.plist */,
+ 4265C3B926AF74F800BD1DB2 /* AppAttestProviderFactories.swift */,
+ 4265C3BD26AF7A6600BD1DB2 /* YourCustomAppCheckProvider.swift */,
+ );
+ path = AppCheckSnippetsSwift;
+ sourceTree = "";
+ };
+ 42A83E6D26AF6E5C00097CA3 = {
+ isa = PBXGroup;
+ children = (
+ 4265C38926AF71E100BD1DB2 /* AppCheckSnippetsObjC */,
+ 4265C3A626AF723800BD1DB2 /* AppCheckSnippetsSwift */,
+ 8D77260B2D2874BA00537A0B /* Frameworks */,
+ 4265C38826AF71E100BD1DB2 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 8D77260B2D2874BA00537A0B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 4265C38626AF71E100BD1DB2 /* AppCheckSnippetsObjC */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4265C3A026AF71E300BD1DB2 /* Build configuration list for PBXNativeTarget "AppCheckSnippetsObjC" */;
+ buildPhases = (
+ 4265C38326AF71E100BD1DB2 /* Sources */,
+ 4265C38426AF71E100BD1DB2 /* Frameworks */,
+ 4265C38526AF71E100BD1DB2 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = AppCheckSnippetsObjC;
+ productName = AppCheckSnippetsObjC;
+ productReference = 4265C38726AF71E100BD1DB2 /* AppCheckSnippetsObjC.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 4265C3A426AF723800BD1DB2 /* AppCheckSnippetsSwift */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4265C3B626AF723900BD1DB2 /* Build configuration list for PBXNativeTarget "AppCheckSnippetsSwift" */;
+ buildPhases = (
+ 4265C3A126AF723800BD1DB2 /* Sources */,
+ 4265C3A226AF723800BD1DB2 /* Frameworks */,
+ 4265C3A326AF723800BD1DB2 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = AppCheckSnippetsSwift;
+ productName = AppCheckSnippetsSwift;
+ productReference = 4265C3A526AF723800BD1DB2 /* AppCheckSnippetsSwift.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 42A83E6E26AF6E5C00097CA3 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1250;
+ LastUpgradeCheck = 1250;
+ TargetAttributes = {
+ 4265C38626AF71E100BD1DB2 = {
+ CreatedOnToolsVersion = 12.5;
+ };
+ 4265C3A426AF723800BD1DB2 = {
+ CreatedOnToolsVersion = 12.5;
+ };
+ };
+ };
+ buildConfigurationList = 42A83E7126AF6E5C00097CA3 /* Build configuration list for PBXProject "AppCheckSnippets" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 42A83E6D26AF6E5C00097CA3;
+ packageReferences = (
+ 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
+ productRefGroup = 4265C38826AF71E100BD1DB2 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4265C38626AF71E100BD1DB2 /* AppCheckSnippetsObjC */,
+ 4265C3A426AF723800BD1DB2 /* AppCheckSnippetsSwift */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 4265C38526AF71E100BD1DB2 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4265C39A26AF71E300BD1DB2 /* LaunchScreen.storyboard in Resources */,
+ 4265C39726AF71E300BD1DB2 /* Assets.xcassets in Resources */,
+ 4265C39526AF71E100BD1DB2 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4265C3A326AF723800BD1DB2 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4265C3B426AF723900BD1DB2 /* LaunchScreen.storyboard in Resources */,
+ 4265C3B126AF723900BD1DB2 /* Assets.xcassets in Resources */,
+ 4265C3AF26AF723800BD1DB2 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4265C38326AF71E100BD1DB2 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4265C39226AF71E100BD1DB2 /* ViewController.m in Sources */,
+ 4265C3C026AF7A7E00BD1DB2 /* YourCustomAppCheckProvider.m in Sources */,
+ 4265C38C26AF71E100BD1DB2 /* AppDelegate.m in Sources */,
+ 4265C39D26AF71E300BD1DB2 /* main.m in Sources */,
+ 4265C3BC26AF775A00BD1DB2 /* AppAttestProviderFactories.m in Sources */,
+ 4265C38F26AF71E100BD1DB2 /* SceneDelegate.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4265C3A126AF723800BD1DB2 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4265C3BE26AF7A6600BD1DB2 /* YourCustomAppCheckProvider.swift in Sources */,
+ 4265C3BA26AF74F800BD1DB2 /* AppAttestProviderFactories.swift in Sources */,
+ 4265C3AC26AF723800BD1DB2 /* ViewController.swift in Sources */,
+ 4265C3A826AF723800BD1DB2 /* AppDelegate.swift in Sources */,
+ 4265C3AA26AF723800BD1DB2 /* SceneDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 4265C39326AF71E100BD1DB2 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4265C39426AF71E100BD1DB2 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 4265C39826AF71E300BD1DB2 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4265C39926AF71E300BD1DB2 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ 4265C3AD26AF723800BD1DB2 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4265C3AE26AF723800BD1DB2 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 4265C3B226AF723900BD1DB2 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4265C3B326AF723900BD1DB2 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 4265C39E26AF71E300BD1DB2 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = AppCheckSnippetsObjC/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.example.AppCheckSnippetsObjC;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4265C39F26AF71E300BD1DB2 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = AppCheckSnippetsObjC/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.example.AppCheckSnippetsObjC;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 4265C3B726AF723900BD1DB2 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = AppCheckSnippetsSwift/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.example.AppCheckSnippetsSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4265C3B826AF723900BD1DB2 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = AppCheckSnippetsSwift/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.example.AppCheckSnippetsSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 42A83E7226AF6E5C00097CA3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 42A83E7326AF6E5C00097CA3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4265C3A026AF71E300BD1DB2 /* Build configuration list for PBXNativeTarget "AppCheckSnippetsObjC" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4265C39E26AF71E300BD1DB2 /* Debug */,
+ 4265C39F26AF71E300BD1DB2 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4265C3B626AF723900BD1DB2 /* Build configuration list for PBXNativeTarget "AppCheckSnippetsSwift" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4265C3B726AF723900BD1DB2 /* Debug */,
+ 4265C3B826AF723900BD1DB2 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 42A83E7126AF6E5C00097CA3 /* Build configuration list for PBXProject "AppCheckSnippets" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 42A83E7226AF6E5C00097CA3 /* Debug */,
+ 42A83E7326AF6E5C00097CA3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7726072D2874A100537A0B /* FirebaseAppCheck */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAppCheck;
+ };
+ 8D7726092D2874A100537A0B /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+ 8D77260C2D2874BA00537A0B /* FirebaseAppCheck */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAppCheck;
+ };
+ 8D77260E2D2874BA00537A0B /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726062D2874A100537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = 42A83E6E26AF6E5C00097CA3 /* Project object */;
+}
diff --git a/appcheck/AppCheckSnippetsObjC/AppAttestProviderFactories.m b/appcheck/AppCheckSnippetsObjC/AppAttestProviderFactories.m
new file mode 100644
index 00000000..2d892ab9
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/AppAttestProviderFactories.m
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+@import FirebaseAppCheck;
+
+// [START appcheck_simple_appattest_factory]
+@interface YourSimpleAppCheckProviderFactory : NSObject
+@end
+
+@implementation YourSimpleAppCheckProviderFactory
+
+- (nullable id)createProviderWithApp:(nonnull FIRApp *)app {
+ return [[FIRAppAttestProvider alloc] initWithApp:app];
+}
+
+@end
+// [END appcheck_simple_appattest_factory]
+
+// [START appcheck_appattest_factory]
+@interface YourAppCheckProviderFactory : NSObject
+@end
+
+@implementation YourAppCheckProviderFactory
+
+- (nullable id)createProviderWithApp:(nonnull FIRApp *)app {
+ if (@available(iOS 14.0, *)) {
+ return [[FIRAppAttestProvider alloc] initWithApp:app];
+ } else {
+ return [[FIRDeviceCheckProvider alloc] initWithApp:app];
+ }
+}
+
+@end
+// [START appcheck_appattest_factory]
diff --git a/appcheck/AppCheckSnippetsObjC/AppDelegate.h b/appcheck/AppCheckSnippetsObjC/AppDelegate.h
new file mode 100644
index 00000000..c142da10
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/AppDelegate.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+
+@interface AppDelegate : UIResponder
+
+
+@end
+
diff --git a/appcheck/AppCheckSnippetsObjC/AppDelegate.m b/appcheck/AppCheckSnippetsObjC/AppDelegate.m
new file mode 100644
index 00000000..2bf07506
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/AppDelegate.m
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 "AppDelegate.h"
+@import FirebaseCore;
+@import FirebaseAppCheck;
+
+@interface AppDelegate ()
+@end
+
+@interface YourAppCheckProviderFactory : NSObject
+@end
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ return YES;
+}
+
+- (void)initCustom {
+ // [START appcheck_initialize_custom]
+ YourAppCheckProviderFactory *providerFactory =
+ [[YourAppCheckProviderFactory alloc] init];
+ [FIRAppCheck setAppCheckProviderFactory:providerFactory];
+
+ [FIRApp configure];
+ // [END appcheck_initialize_custom]
+}
+
+- (void)initDebug {
+ // [START appcheck_initialize_debug]
+ FIRAppCheckDebugProviderFactory *providerFactory =
+ [[FIRAppCheckDebugProviderFactory alloc] init];
+ [FIRAppCheck setAppCheckProviderFactory:providerFactory];
+
+ // Use Firebase library to configure APIs
+ [FIRApp configure];
+ // [END appcheck_initialize_debug]
+}
+
+- (void)nonFirebaseBackend {
+ // [START appcheck_nonfirebase]
+ [[FIRAppCheck appCheck] tokenForcingRefresh:NO
+ completion:^(FIRAppCheckToken * _Nullable token,
+ NSError * _Nullable error) {
+ if (error != nil) {
+ // Handle any errors if the token was not retrieved.
+ NSLog(@"Unable to retrieve App Check token: %@", error);
+ return;
+ }
+ if (token == nil) {
+ NSLog(@"Unable to retrieve App Check token.");
+ return;
+ }
+
+ // Get the raw App Check token string.
+ NSString *tokenString = token.token;
+
+ // Include the App Check token with requests to your server.
+ NSURL *url = [[NSURL alloc] initWithString:@"https://yourbackend.example.com/yourApiEndpoint"];
+ NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
+ [request setHTTPMethod:@"GET"];
+ [request setValue:tokenString forHTTPHeaderField:@"X-Firebase-AppCheck"];
+
+ NSURLSessionDataTask *task =
+ [[NSURLSession sharedSession] dataTaskWithRequest:request
+ completionHandler:^(NSData * _Nullable data,
+ NSURLResponse * _Nullable response,
+ NSError * _Nullable error) {
+ // Handle response from your backend.
+ }];
+ [task resume];
+ }];
+ // [END appcheck_nonfirebase]
+}
+
+#pragma mark - UISceneSession lifecycle
+
+
+- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
+}
+
+
+- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+}
+
+
+@end
diff --git a/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AccentColor.colorset/Contents.json b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 00000000..eb878970
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AppIcon.appiconset/Contents.json b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..9221b9bb
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "scale" : "1x",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsObjC/Assets.xcassets/Contents.json b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsObjC/Base.lproj/LaunchScreen.storyboard b/appcheck/AppCheckSnippetsObjC/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..865e9329
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appcheck/AppCheckSnippetsObjC/Base.lproj/Main.storyboard b/appcheck/AppCheckSnippetsObjC/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..808a21ce
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appcheck/AppCheckSnippetsObjC/Info.plist b/appcheck/AppCheckSnippetsObjC/Info.plist
new file mode 100644
index 00000000..72bf2c4f
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/Info.plist
@@ -0,0 +1,66 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ SceneDelegate
+ UISceneStoryboardFile
+ Main
+
+
+
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/appcheck/AppCheckSnippetsObjC/SceneDelegate.h b/appcheck/AppCheckSnippetsObjC/SceneDelegate.h
new file mode 100644
index 00000000..a0ab2fd4
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/SceneDelegate.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+
+@interface SceneDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow * window;
+
+@end
+
diff --git a/appcheck/AppCheckSnippetsObjC/SceneDelegate.m b/appcheck/AppCheckSnippetsObjC/SceneDelegate.m
new file mode 100644
index 00000000..b6032205
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/SceneDelegate.m
@@ -0,0 +1,66 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 "SceneDelegate.h"
+
+@interface SceneDelegate ()
+
+@end
+
+@implementation SceneDelegate
+
+
+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
+ // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+ // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+ // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+}
+
+
+- (void)sceneDidDisconnect:(UIScene *)scene {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+}
+
+
+- (void)sceneDidBecomeActive:(UIScene *)scene {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+}
+
+
+- (void)sceneWillResignActive:(UIScene *)scene {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+}
+
+
+- (void)sceneWillEnterForeground:(UIScene *)scene {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+}
+
+
+- (void)sceneDidEnterBackground:(UIScene *)scene {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+}
+
+
+@end
diff --git a/invites/InvitesExample/ViewController.h b/appcheck/AppCheckSnippetsObjC/ViewController.h
similarity index 91%
rename from invites/InvitesExample/ViewController.h
rename to appcheck/AppCheckSnippetsObjC/ViewController.h
index 179f8331..838d309e 100644
--- a/invites/InvitesExample/ViewController.h
+++ b/appcheck/AppCheckSnippetsObjC/ViewController.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) Google Inc.
+// Copyright (c) 2021 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,8 +14,10 @@
// limitations under the License.
//
-@import UIKit;
+#import
@interface ViewController : UIViewController
+
@end
+
diff --git a/appcheck/AppCheckSnippetsObjC/ViewController.m b/appcheck/AppCheckSnippetsObjC/ViewController.m
new file mode 100644
index 00000000..d25919ef
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/ViewController.m
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 "ViewController.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+
+@end
diff --git a/appcheck/AppCheckSnippetsObjC/YourCustomAppCheckProvider.m b/appcheck/AppCheckSnippetsObjC/YourCustomAppCheckProvider.m
new file mode 100644
index 00000000..95a5821d
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/YourCustomAppCheckProvider.m
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+@import FirebaseAppCheck;
+
+// [START appcheck_custom_provider]
+@interface YourCustomAppCheckProvider : NSObject
+
+@property FIRApp *app;
+
+- (id)initWithApp:(FIRApp *)app;
+
+@end
+
+@implementation YourCustomAppCheckProvider
+
+- (id)initWithApp:app {
+ self = [super init];
+ if (self) {
+ self.app = app;
+ }
+ return self;
+}
+
+- (void)getTokenWithCompletion:(nonnull void (^)(FIRAppCheckToken * _Nullable,
+ NSError * _Nullable))handler {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // Logic to exchange proof of authenticity for an App Check token.
+ // [START_EXCLUDE]
+ double expirationFromServer = 1234.0;
+ NSString *tokenFromServer = @"token";
+ // [END_EXCLUDE]
+
+ // Create FIRAppCheckToken object.
+ NSTimeInterval exp = expirationFromServer;
+ FIRAppCheckToken *token
+ = [[FIRAppCheckToken alloc] initWithToken:tokenFromServer
+ expirationDate:[NSDate dateWithTimeIntervalSince1970:exp]];
+
+ // Pass the token or error to the completion handler.
+ handler(token, nil);
+ });
+}
+
+@end
+// [END appcheck_custom_provider]
+
+// [START appcheck_custom_provider_factory]
+@interface YourCustomAppCheckProviderFactory : NSObject
+@end
+
+@implementation YourCustomAppCheckProviderFactory
+
+- (nullable id)createProviderWithApp:(FIRApp *)app {
+ return [[YourCustomAppCheckProvider alloc] initWithApp:app];
+}
+
+@end
+// [END appcheck_custom_provider_factory]
diff --git a/appcheck/AppCheckSnippetsObjC/main.m b/appcheck/AppCheckSnippetsObjC/main.m
new file mode 100644
index 00000000..a440f36e
--- /dev/null
+++ b/appcheck/AppCheckSnippetsObjC/main.m
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ NSString * appDelegateClassName;
+ @autoreleasepool {
+ // Setup code that might create autoreleased objects goes here.
+ appDelegateClassName = NSStringFromClass([AppDelegate class]);
+ }
+ return UIApplicationMain(argc, argv, nil, appDelegateClassName);
+}
diff --git a/appcheck/AppCheckSnippetsSwift/AppAttestProviderFactories.swift b/appcheck/AppCheckSnippetsSwift/AppAttestProviderFactories.swift
new file mode 100644
index 00000000..cb209737
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/AppAttestProviderFactories.swift
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 FirebaseCore
+import FirebaseAppCheck
+
+// [START appcheck_simple_appattest_factory]
+class YourSimpleAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
+ func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
+ return AppAttestProvider(app: app)
+ }
+}
+// [END appcheck_simple_appattest_factory]
+
+// [START appcheck_appattest_factory]
+class YourAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
+ func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
+ if #available(iOS 14.0, *) {
+ return AppAttestProvider(app: app)
+ } else {
+ return DeviceCheckProvider(app: app)
+ }
+ }
+}
+// [END appcheck_appattest_factory]
diff --git a/appcheck/AppCheckSnippetsSwift/AppDelegate.swift b/appcheck/AppCheckSnippetsSwift/AppDelegate.swift
new file mode 100644
index 00000000..5ea067fc
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/AppDelegate.swift
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 FirebaseCore
+import FirebaseAppCheck
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ return true
+ }
+
+ func initCustom() {
+ // [START appcheck_initialize_custom]
+ let providerFactory = YourAppCheckProviderFactory()
+ AppCheck.setAppCheckProviderFactory(providerFactory)
+
+ FirebaseApp.configure()
+ // [END appcheck_initialize_custom]
+ }
+
+ func initDebug() {
+ // [START appcheck_initialize_debug]
+ let providerFactory = AppCheckDebugProviderFactory()
+ AppCheck.setAppCheckProviderFactory(providerFactory)
+
+ FirebaseApp.configure()
+ // [END appcheck_initialize_debug]
+ }
+
+ func nonFirebaseBackend() async {
+ // [START appcheck_nonfirebase]
+
+ do {
+ let token = try await AppCheck.appCheck().token(forcingRefresh: false)
+
+ // Get the raw App Check token string.
+ let tokenString = token.token
+
+ // Include the App Check token with requests to your server.
+ let url = URL(string: "https://yourbackend.example.com/yourApiEndpoint")!
+ var request = URLRequest(url: url)
+ request.httpMethod = "GET"
+ request.setValue(tokenString, forHTTPHeaderField: "X-Firebase-AppCheck")
+
+ let task = URLSession.shared.dataTask(with: request) { data, response, error in
+ // Handle response from your backend.
+ }
+ task.resume()
+ } catch(let error) {
+ print("Unable to retrieve App Check token: \(error)")
+ return
+ }
+ // [END appcheck_nonfirebase]
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+}
+
diff --git a/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AccentColor.colorset/Contents.json b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 00000000..eb878970
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AppIcon.appiconset/Contents.json b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..9221b9bb
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "scale" : "1x",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsSwift/Assets.xcassets/Contents.json b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/appcheck/AppCheckSnippetsSwift/Base.lproj/LaunchScreen.storyboard b/appcheck/AppCheckSnippetsSwift/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..865e9329
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appcheck/AppCheckSnippetsSwift/Base.lproj/Main.storyboard b/appcheck/AppCheckSnippetsSwift/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..25a76385
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appcheck/AppCheckSnippetsSwift/Info.plist b/appcheck/AppCheckSnippetsSwift/Info.plist
new file mode 100644
index 00000000..5b531f7b
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/Info.plist
@@ -0,0 +1,66 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ $(PRODUCT_MODULE_NAME).SceneDelegate
+ UISceneStoryboardFile
+ Main
+
+
+
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/appcheck/AppCheckSnippetsSwift/SceneDelegate.swift b/appcheck/AppCheckSnippetsSwift/SceneDelegate.swift
new file mode 100644
index 00000000..dad05973
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/SceneDelegate.swift
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ var window: UIWindow?
+
+
+ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+ // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+ // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+ // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+ guard let _ = (scene as? UIWindowScene) else { return }
+ }
+
+ func sceneDidDisconnect(_ scene: UIScene) {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+ }
+
+ func sceneDidBecomeActive(_ scene: UIScene) {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+ }
+
+ func sceneWillResignActive(_ scene: UIScene) {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+ }
+
+ func sceneWillEnterForeground(_ scene: UIScene) {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+ }
+
+ func sceneDidEnterBackground(_ scene: UIScene) {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+ }
+
+
+}
+
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/ViewController.swift b/appcheck/AppCheckSnippetsSwift/ViewController.swift
similarity index 66%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/ViewController.swift
rename to appcheck/AppCheckSnippetsSwift/ViewController.swift
index e549ffb3..546de4a8 100644
--- a/firoptions/FiroptionConfiguration/FiroptionConfiguration/ViewController.swift
+++ b/appcheck/AppCheckSnippetsSwift/ViewController.swift
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2017 Google Inc.
+// Copyright (c) 2021 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,15 +18,10 @@ import UIKit
class ViewController: UIViewController {
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do any additional setup after loading the view, typically from a nib.
- }
-
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
}
diff --git a/appcheck/AppCheckSnippetsSwift/YourCustomAppCheckProvider.swift b/appcheck/AppCheckSnippetsSwift/YourCustomAppCheckProvider.swift
new file mode 100644
index 00000000..ae4971cc
--- /dev/null
+++ b/appcheck/AppCheckSnippetsSwift/YourCustomAppCheckProvider.swift
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2021 Google Inc.
+//
+// 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 FirebaseCore
+import FirebaseAppCheck
+
+// [START appcheck_custom_provider]
+class YourCustomAppCheckProvider: NSObject, AppCheckProvider {
+ var app: FirebaseApp
+
+ init(withFirebaseApp app: FirebaseApp) {
+ self.app = app
+ super.init()
+ }
+
+ func getToken() async throws -> AppCheckToken {
+ let getTokenTask = Task { () -> AppCheckToken in
+ // [START_EXCLUDE]
+ let expirationFromServer = 1000.0
+ let tokenFromServer = "token"
+ // [END_EXCLUDE]
+
+ // Create AppCheckToken object.
+ let exp = Date(timeIntervalSince1970: expirationFromServer)
+ let token = AppCheckToken(
+ token: tokenFromServer,
+ expirationDate: exp
+ )
+
+ if Date() > exp {
+ throw NSError(domain: "ExampleError", code: 1, userInfo: nil)
+ }
+
+ return token
+ }
+
+ return try await getTokenTask.value
+ }
+
+}
+// [END appcheck_custom_provider]
+
+// [START appcheck_custom_provider_factory]
+class YourCustomAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
+ func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
+ return YourCustomAppCheckProvider(withFirebaseApp: app)
+ }
+}
+// [END appcheck_custom_provider_factory]
diff --git a/crashlytics/CrashlyticsExample.xcodeproj/project.pbxproj b/crashlytics/CrashlyticsExample.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..7c014915
--- /dev/null
+++ b/crashlytics/CrashlyticsExample.xcodeproj/project.pbxproj
@@ -0,0 +1,534 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8D7726132D2876F400537A0B /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726122D2876F400537A0B /* FirebaseCore */; };
+ 8D7726152D2876F400537A0B /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726142D2876F400537A0B /* FirebaseCrashlytics */; };
+ 8D7726172D2876FB00537A0B /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726162D2876FB00537A0B /* FirebaseCore */; };
+ 8D7726192D2876FB00537A0B /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7726182D2876FB00537A0B /* FirebaseCrashlytics */; };
+ 8D8FA34322F4CAB100213E06 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34222F4CAB100213E06 /* AppDelegate.m */; };
+ 8D8FA34622F4CAB100213E06 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34522F4CAB100213E06 /* ViewController.m */; };
+ 8D8FA34922F4CAB100213E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34722F4CAB100213E06 /* Main.storyboard */; };
+ 8D8FA34B22F4CAB200213E06 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */; };
+ 8D8FA34E22F4CAB200213E06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */; };
+ 8D8FA35122F4CAB200213E06 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35022F4CAB200213E06 /* main.m */; };
+ 8D8FA35E22F4CAF700213E06 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */; };
+ 8D8FA36022F4CAF700213E06 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35F22F4CAF700213E06 /* ViewController.swift */; };
+ 8D8FA36322F4CAF700213E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36122F4CAF700213E06 /* Main.storyboard */; };
+ 8D8FA36522F4CAF800213E06 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36422F4CAF800213E06 /* Assets.xcassets */; };
+ 8D8FA36822F4CAF800213E06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 8D8FA33E22F4CAB100213E06 /* CrashlyticsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CrashlyticsExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D8FA34122F4CAB100213E06 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 8D8FA34222F4CAB100213E06 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 8D8FA34422F4CAB100213E06 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
+ 8D8FA34522F4CAB100213E06 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
+ 8D8FA34822F4CAB100213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 8D8FA34D22F4CAB200213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 8D8FA34F22F4CAB200213E06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 8D8FA35022F4CAB200213E06 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 8D8FA35B22F4CAF700213E06 /* CrashlyticsExampleSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CrashlyticsExampleSwift.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 8D8FA35F22F4CAF700213E06 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 8D8FA36222F4CAF700213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 8D8FA36422F4CAF800213E06 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 8D8FA36722F4CAF800213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 8D8FA36922F4CAF800213E06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D8FA33B22F4CAB100213E06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D7726132D2876F400537A0B /* FirebaseCore in Frameworks */,
+ 8D7726152D2876F400537A0B /* FirebaseCrashlytics in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35822F4CAF700213E06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D7726172D2876FB00537A0B /* FirebaseCore in Frameworks */,
+ 8D7726192D2876FB00537A0B /* FirebaseCrashlytics in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 8D7726112D2876F400537A0B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 8D8FA33522F4CAB100213E06 = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA34022F4CAB100213E06 /* CrashlyticsExample */,
+ 8D8FA35C22F4CAF700213E06 /* CrashlyticsExampleSwift */,
+ 8D7726112D2876F400537A0B /* Frameworks */,
+ 8D8FA33F22F4CAB100213E06 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 8D8FA33F22F4CAB100213E06 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA33E22F4CAB100213E06 /* CrashlyticsExample.app */,
+ 8D8FA35B22F4CAF700213E06 /* CrashlyticsExampleSwift.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 8D8FA34022F4CAB100213E06 /* CrashlyticsExample */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA34122F4CAB100213E06 /* AppDelegate.h */,
+ 8D8FA34222F4CAB100213E06 /* AppDelegate.m */,
+ 8D8FA34422F4CAB100213E06 /* ViewController.h */,
+ 8D8FA34522F4CAB100213E06 /* ViewController.m */,
+ 8D8FA34722F4CAB100213E06 /* Main.storyboard */,
+ 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */,
+ 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */,
+ 8D8FA34F22F4CAB200213E06 /* Info.plist */,
+ 8D8FA35022F4CAB200213E06 /* main.m */,
+ );
+ path = CrashlyticsExample;
+ sourceTree = "";
+ };
+ 8D8FA35C22F4CAF700213E06 /* CrashlyticsExampleSwift */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */,
+ 8D8FA35F22F4CAF700213E06 /* ViewController.swift */,
+ 8D8FA36122F4CAF700213E06 /* Main.storyboard */,
+ 8D8FA36422F4CAF800213E06 /* Assets.xcassets */,
+ 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */,
+ 8D8FA36922F4CAF800213E06 /* Info.plist */,
+ );
+ path = CrashlyticsExampleSwift;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D8FA33D22F4CAB100213E06 /* CrashlyticsExample */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8D8FA35422F4CAB200213E06 /* Build configuration list for PBXNativeTarget "CrashlyticsExample" */;
+ buildPhases = (
+ 8D8FA33A22F4CAB100213E06 /* Sources */,
+ 8D8FA33B22F4CAB100213E06 /* Frameworks */,
+ 8D8FA33C22F4CAB100213E06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = CrashlyticsExample;
+ productName = CrashlyticsExample;
+ productReference = 8D8FA33E22F4CAB100213E06 /* CrashlyticsExample.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 8D8FA35A22F4CAF700213E06 /* CrashlyticsExampleSwift */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8D8FA36C22F4CAF800213E06 /* Build configuration list for PBXNativeTarget "CrashlyticsExampleSwift" */;
+ buildPhases = (
+ 8D8FA35722F4CAF700213E06 /* Sources */,
+ 8D8FA35822F4CAF700213E06 /* Frameworks */,
+ 8D8FA35922F4CAF700213E06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = CrashlyticsExampleSwift;
+ productName = CrashlyticsExampleSwift;
+ productReference = 8D8FA35B22F4CAF700213E06 /* CrashlyticsExampleSwift.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 8D8FA33622F4CAB100213E06 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1020;
+ LastUpgradeCheck = 1230;
+ ORGANIZATIONNAME = Firebase;
+ TargetAttributes = {
+ 8D8FA33D22F4CAB100213E06 = {
+ CreatedOnToolsVersion = 10.2;
+ };
+ 8D8FA35A22F4CAF700213E06 = {
+ CreatedOnToolsVersion = 10.2;
+ };
+ };
+ };
+ buildConfigurationList = 8D8FA33922F4CAB100213E06 /* Build configuration list for PBXProject "CrashlyticsExample" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 8D8FA33522F4CAB100213E06;
+ packageReferences = (
+ 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
+ productRefGroup = 8D8FA33F22F4CAB100213E06 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D8FA33D22F4CAB100213E06 /* CrashlyticsExample */,
+ 8D8FA35A22F4CAF700213E06 /* CrashlyticsExampleSwift */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D8FA33C22F4CAB100213E06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA34E22F4CAB200213E06 /* LaunchScreen.storyboard in Resources */,
+ 8D8FA34B22F4CAB200213E06 /* Assets.xcassets in Resources */,
+ 8D8FA34922F4CAB100213E06 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35922F4CAF700213E06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA36822F4CAF800213E06 /* LaunchScreen.storyboard in Resources */,
+ 8D8FA36522F4CAF800213E06 /* Assets.xcassets in Resources */,
+ 8D8FA36322F4CAF700213E06 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D8FA33A22F4CAB100213E06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA34622F4CAB100213E06 /* ViewController.m in Sources */,
+ 8D8FA35122F4CAB200213E06 /* main.m in Sources */,
+ 8D8FA34322F4CAB100213E06 /* AppDelegate.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35722F4CAF700213E06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA36022F4CAF700213E06 /* ViewController.swift in Sources */,
+ 8D8FA35E22F4CAF700213E06 /* AppDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 8D8FA34722F4CAB100213E06 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA34822F4CAB100213E06 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA34D22F4CAB200213E06 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA36122F4CAF700213E06 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA36222F4CAF700213E06 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA36722F4CAF800213E06 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 8D8FA35222F4CAB200213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.2;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 8D8FA35322F4CAB200213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.2;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 8D8FA35522F4CAB200213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = CrashlyticsExample/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.CrashlyticsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 8D8FA35622F4CAB200213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = CrashlyticsExample/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.CrashlyticsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 8D8FA36A22F4CAF800213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = CrashlyticsExampleSwift/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.CrashlyticsExampleSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 8D8FA36B22F4CAF800213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = CrashlyticsExampleSwift/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.CrashlyticsExampleSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 8D8FA33922F4CAB100213E06 /* Build configuration list for PBXProject "CrashlyticsExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA35222F4CAB200213E06 /* Debug */,
+ 8D8FA35322F4CAB200213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8D8FA35422F4CAB200213E06 /* Build configuration list for PBXNativeTarget "CrashlyticsExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA35522F4CAB200213E06 /* Debug */,
+ 8D8FA35622F4CAB200213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8D8FA36C22F4CAF800213E06 /* Build configuration list for PBXNativeTarget "CrashlyticsExampleSwift" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA36A22F4CAF800213E06 /* Debug */,
+ 8D8FA36B22F4CAF800213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7726122D2876F400537A0B /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+ 8D7726142D2876F400537A0B /* FirebaseCrashlytics */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCrashlytics;
+ };
+ 8D7726162D2876FB00537A0B /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+ 8D7726182D2876FB00537A0B /* FirebaseCrashlytics */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7726102D2876EB00537A0B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCrashlytics;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = 8D8FA33622F4CAB100213E06 /* Project object */;
+}
diff --git a/crashlytics/CrashlyticsExample/AppDelegate.h b/crashlytics/CrashlyticsExample/AppDelegate.h
new file mode 100644
index 00000000..a9861fa2
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/AppDelegate.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/crashlytics/CrashlyticsExample/AppDelegate.m b/crashlytics/CrashlyticsExample/AppDelegate.m
new file mode 100644
index 00000000..69381fe8
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/AppDelegate.m
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseCore;
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [FIRApp configure];
+ return YES;
+}
+
+
+@end
diff --git a/invites/InvitesExampleSwift/Images.xcassets/AppIcon.appiconset/Contents.json b/crashlytics/CrashlyticsExample/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 67%
rename from invites/InvitesExampleSwift/Images.xcassets/AppIcon.appiconset/Contents.json
rename to crashlytics/CrashlyticsExample/Assets.xcassets/AppIcon.appiconset/Contents.json
index 36d2c80d..d8db8d65 100644
--- a/invites/InvitesExampleSwift/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/crashlytics/CrashlyticsExample/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,5 +1,15 @@
{
"images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
{
"idiom" : "iphone",
"size" : "29x29",
@@ -30,6 +40,16 @@
"size" : "60x60",
"scale" : "3x"
},
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
{
"idiom" : "ipad",
"size" : "29x29",
@@ -59,6 +79,16 @@
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
}
],
"info" : {
diff --git a/crashlytics/CrashlyticsExample/Assets.xcassets/Contents.json b/crashlytics/CrashlyticsExample/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/crashlytics/CrashlyticsExample/Base.lproj/LaunchScreen.storyboard b/crashlytics/CrashlyticsExample/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..bfa36129
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crashlytics/CrashlyticsExample/Base.lproj/Main.storyboard b/crashlytics/CrashlyticsExample/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..942f0bc4
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crashlytics/CrashlyticsExample/Info.plist b/crashlytics/CrashlyticsExample/Info.plist
new file mode 100644
index 00000000..16be3b68
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/invites/InvitesExample/SignInViewController.h b/crashlytics/CrashlyticsExample/ViewController.h
similarity index 87%
rename from invites/InvitesExample/SignInViewController.h
rename to crashlytics/CrashlyticsExample/ViewController.h
index 3369cd1e..f543b8a0 100644
--- a/invites/InvitesExample/SignInViewController.h
+++ b/crashlytics/CrashlyticsExample/ViewController.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) Google Inc.
+// Copyright (c) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,8 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
+
#import
-@interface SignInViewController : UIViewController
+@interface ViewController : UIViewController
+
+
+@end
-@end
\ No newline at end of file
diff --git a/crashlytics/CrashlyticsExample/ViewController.m b/crashlytics/CrashlyticsExample/ViewController.m
new file mode 100644
index 00000000..3137e140
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/ViewController.m
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseCrashlytics;
+
+#import "ViewController.h"
+
+@interface ViewController ()
+
+@end
+
+// [START forceCrash]
+@implementation ViewController
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Do any additional setup after loading the view, typically from a nib.
+
+ UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
+ button.frame = CGRectMake(20, 50, 100, 30);
+ [button setTitle:@"Crash" forState:UIControlStateNormal];
+ [button addTarget:self action:@selector(crashButtonTapped:)
+ forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:button];
+}
+
+- (IBAction)crashButtonTapped:(id)sender {
+ @[][1];
+}
+// [END forceCrash]
+
+- (void)customizeStackTraces {
+ // [START customizeStackTraces]
+ FIRExceptionModel *model =
+ [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
+ model.stackTrace = @[
+ [FIRStackFrame stackFrameWithSymbol:@"makeError" file:@"handler.js" line:495],
+ [FIRStackFrame stackFrameWithSymbol:@"then" file:@"routes.js" line:102],
+ [FIRStackFrame stackFrameWithSymbol:@"main" file:@"app.js" line:12],
+ ];
+
+ [[FIRCrashlytics crashlytics] recordExceptionModel:model];
+ // [END customizeStackTraces]
+}
+
+- (void)customizeStackTracesAddress {
+ // [START customizeStackTracesAddress]
+ FIRExceptionModel *model =
+ [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
+ model.stackTrace = @[
+ [FIRStackFrame stackFrameWithAddress:0xfa12123],
+ [FIRStackFrame stackFrameWithAddress:12412412],
+ [FIRStackFrame stackFrameWithAddress:194129124],
+ ];
+
+
+ [[FIRCrashlytics crashlytics] recordExceptionModel:model];
+ // [END customizeStackTracesAddress]
+}
+
+- (void)setCustomKey {
+ // [START setCustomKey]
+ // Set int_key to 100.
+ [[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];
+
+ // Set str_key to "hello".
+ [[FIRCrashlytics crashlytics] setCustomValue:@"hello" forKey:@"str_key"];
+ // [END setCustomKey]
+}
+
+- (void)setCustomValue {
+ // [START setCustomValue]
+ [[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];
+
+ // Set int_key to 50 from 100.
+ [[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];
+ // [END setCustomValue]
+}
+
+- (void)setCustomKeys {
+ // [START setCustomKeys]
+ NSDictionary *keysAndValues =
+ @{@"string key" : @"string value",
+ @"string key 2" : @"string value 2",
+ @"boolean key" : @(YES),
+ @"boolean key 2" : @(NO),
+ @"float key" : @(1.01),
+ @"float key 2" : @(2.02)};
+
+ [[FIRCrashlytics crashlytics] setCustomKeysAndValues: keysAndValues];
+ // [END setCustomKeys]
+}
+
+- (void)enableOptIn {
+ // [START enableOptIn]
+ [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
+ // [END enableOptIn]
+}
+
+- (void)logExceptions {
+ // [START createError]
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"The request failed.", nil),
+ NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The response returned a 404.", nil),
+ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Does this page exist?", nil),
+ @"ProductID": @"123456",
+ @"View": @"MainView",
+ };
+
+ NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
+ code:-1001
+ userInfo:userInfo];
+ // [END createError]
+
+ // [START recordError]
+ [[FIRCrashlytics crashlytics] recordError:error];
+ // [END recordError]
+}
+
+- (void)setUserId {
+ // [START setUserId]
+ [[FIRCrashlytics crashlytics] setUserID:@"123456789"];
+ // [END setUserId]
+}
+
+@end
diff --git a/crashlytics/CrashlyticsExample/main.m b/crashlytics/CrashlyticsExample/main.m
new file mode 100644
index 00000000..8d31108d
--- /dev/null
+++ b/crashlytics/CrashlyticsExample/main.m
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/crashlytics/CrashlyticsExampleSwift/AppDelegate.swift b/crashlytics/CrashlyticsExampleSwift/AppDelegate.swift
new file mode 100644
index 00000000..6a384187
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/AppDelegate.swift
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseCore
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ FirebaseApp.configure()
+ return true
+ }
+
+}
+
diff --git a/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json b/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..d8db8d65
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/Contents.json b/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/crashlytics/CrashlyticsExampleSwift/Base.lproj/LaunchScreen.storyboard b/crashlytics/CrashlyticsExampleSwift/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..bfa36129
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crashlytics/CrashlyticsExampleSwift/Base.lproj/Main.storyboard b/crashlytics/CrashlyticsExampleSwift/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..f1bcf384
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crashlytics/CrashlyticsExampleSwift/Info.plist b/crashlytics/CrashlyticsExampleSwift/Info.plist
new file mode 100644
index 00000000..16be3b68
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/crashlytics/CrashlyticsExampleSwift/ViewController.swift b/crashlytics/CrashlyticsExampleSwift/ViewController.swift
new file mode 100644
index 00000000..55f61401
--- /dev/null
+++ b/crashlytics/CrashlyticsExampleSwift/ViewController.swift
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseCrashlytics
+
+// [START forceCrash]
+class ViewController: UIViewController {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ // Do any additional setup after loading the view, typically from a nib.
+
+ let button = UIButton(type: .roundedRect)
+ button.frame = CGRect(x: 20, y: 50, width: 100, height: 30)
+ button.setTitle("Crash", for: [])
+ button.addTarget(self, action: #selector(self.crashButtonTapped(_:)), for: .touchUpInside)
+ view.addSubview(button)
+ }
+
+ @IBAction func crashButtonTapped(_ sender: AnyObject) {
+ fatalError()
+ }
+ // [END forceCrash]
+
+ // [START crashlytics_define]
+ lazy var crashlytics = Crashlytics.crashlytics()
+ // [END crashlytics_define]
+
+
+ func customizeStackTraces() {
+ // [START customizeStackTraces]
+ var ex = ExceptionModel(name:"FooException", reason:"There was a foo.")
+ ex.stackTrace = [
+ StackFrame(symbol:"makeError", file:"handler.js", line:495),
+ StackFrame(symbol:"then", file:"routes.js", line:102),
+ StackFrame(symbol:"main", file:"app.js", line:12),
+ ]
+
+ crashlytics.record(exceptionModel:ex)
+ // [END customizeStackTraces]
+ }
+
+ func customizeStackTracesAddress() {
+ // [START customizeStackTracesAddress]
+ var ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
+ ex.stackTrace = [
+ StackFrame(address:0xfa12123),
+ StackFrame(address:12412412),
+ StackFrame(address:194129124),
+ ]
+
+ crashlytics.record(exceptionModel:ex)
+ // [END customizeStackTracesAddress]
+ }
+
+ func setCustomKey() {
+ // [START setCustomKey]
+ // Set int_key to 100.
+ Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")
+
+ // Set str_key to "hello".
+ Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")
+ // [END setCustomKey]
+ }
+
+ func setCustomValue() {
+ // [START setCustomValue]
+ Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")
+
+ // Set int_key to 50 from 100.
+ Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")
+ // [END setCustomValue]
+ }
+
+ func setCustomKeys() {
+ // [START setCustomKeys]
+ let keysAndValues = [
+ "string key" : "string value",
+ "string key 2" : "string value 2",
+ "boolean key" : true,
+ "boolean key 2" : false,
+ "float key" : 1.01,
+ "float key 2" : 2.02
+ ] as [String : Any]
+
+ Crashlytics.crashlytics().setCustomKeysAndValues(keysAndValues)
+ // [END setCustomKeys]
+ }
+
+ func enableOptIn() {
+ // [START enableOptIn]
+ Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
+ // [END enableOptIn]
+ }
+
+ func logExceptions() {
+ // [START createError]
+ let userInfo = [
+ NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""),
+ NSLocalizedFailureReasonErrorKey: NSLocalizedString("The response returned a 404.", comment: ""),
+ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Does this page exist?", comment: ""),
+ "ProductID": "123456",
+ "View": "MainView"
+ ]
+
+ let error = NSError.init(domain: NSCocoaErrorDomain,
+ code: -1001,
+ userInfo: userInfo)
+ // [END createError]
+
+ // [START recordError]
+ Crashlytics.crashlytics().record(error: error)
+ // [END recordError]
+ }
+
+ func setUserId() {
+ // [START setUserId]
+ Crashlytics.crashlytics().setUserID("123456789")
+ // [END setUserId]
+ }
+}
diff --git a/database/DatabaseReference.xcodeproj/project.pbxproj b/database/DatabaseReference.xcodeproj/project.pbxproj
index 1401de77..f4c85ed6 100644
--- a/database/DatabaseReference.xcodeproj/project.pbxproj
+++ b/database/DatabaseReference.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -11,6 +11,8 @@
8D19B3751EA7D49400451CA7 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D19B3731EA7D49400451CA7 /* ViewController.m */; };
8D19B3781EA7D4A300451CA7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D19B3761EA7D4A300451CA7 /* AppDelegate.swift */; };
8D19B3791EA7D4A300451CA7 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D19B3771EA7D4A300451CA7 /* ViewController.swift */; };
+ 8D474FD62D28A9CF000B5C38 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 8D474FD52D28A9CF000B5C38 /* FirebaseAuth */; };
+ 8D474FD82D28A9CF000B5C38 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = 8D474FD72D28A9CF000B5C38 /* FirebaseDatabase */; };
8DDD574C1EA6D39D00DD14EB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8DDD574A1EA6D39D00DD14EB /* Main.storyboard */; };
8DDD574E1EA6D39D00DD14EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8DDD574D1EA6D39D00DD14EB /* Assets.xcassets */; };
8DDD57511EA6D39D00DD14EB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8DDD574F1EA6D39D00DD14EB /* LaunchScreen.storyboard */; };
@@ -35,12 +37,21 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D474FD82D28A9CF000B5C38 /* FirebaseDatabase in Frameworks */,
+ 8D474FD62D28A9CF000B5C38 /* FirebaseAuth in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 8D474FD42D28A9CF000B5C38 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
8D5CA1551EA6D5490024095C /* ObjC */ = {
isa = PBXGroup;
children = (
@@ -65,6 +76,7 @@
isa = PBXGroup;
children = (
8DDD57451EA6D39D00DD14EB /* DatabaseReference */,
+ 8D474FD42D28A9CF000B5C38 /* Frameworks */,
8DDD57441EA6D39D00DD14EB /* Products */,
);
sourceTree = "";
@@ -117,7 +129,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
- LastUpgradeCheck = 0830;
+ LastUpgradeCheck = 1230;
ORGANIZATIONNAME = "Morgan Chen";
TargetAttributes = {
8DDD57421EA6D39D00DD14EB = {
@@ -132,10 +144,14 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
Base,
);
mainGroup = 8DDD573A1EA6D39D00DD14EB;
+ packageReferences = (
+ 8D474FD32D28A9C3000B5C38 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
productRefGroup = 8DDD57441EA6D39D00DD14EB /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -233,12 +249,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -278,10 +295,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -293,12 +312,16 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = DatabaseReference/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.referencecode.DatabaseReference;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -308,11 +331,15 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = DatabaseReference/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.referencecode.DatabaseReference;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -338,6 +365,30 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D474FD32D28A9C3000B5C38 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D474FD52D28A9CF000B5C38 /* FirebaseAuth */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D474FD32D28A9C3000B5C38 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAuth;
+ };
+ 8D474FD72D28A9CF000B5C38 /* FirebaseDatabase */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D474FD32D28A9C3000B5C38 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseDatabase;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 8DDD573B1EA6D39D00DD14EB /* Project object */;
}
diff --git a/database/DatabaseReference.xcworkspace/contents.xcworkspacedata b/database/DatabaseReference.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index b4e48b12..00000000
--- a/database/DatabaseReference.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/database/DatabaseReference/objc/AppDelegate.m b/database/DatabaseReference/objc/AppDelegate.m
index b08eec1b..91461ffc 100644
--- a/database/DatabaseReference/objc/AppDelegate.m
+++ b/database/DatabaseReference/objc/AppDelegate.m
@@ -14,7 +14,8 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseCore;
+@import FirebaseDatabase;
#import "AppDelegate.h"
diff --git a/database/DatabaseReference/objc/ViewController.m b/database/DatabaseReference/objc/ViewController.m
index 457667d0..fa1844f1 100644
--- a/database/DatabaseReference/objc/ViewController.m
+++ b/database/DatabaseReference/objc/ViewController.m
@@ -13,7 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-@import Firebase;
+
+@import FirebaseAuth;
+@import FirebaseDatabase;
#import "ViewController.h"
@@ -25,16 +27,6 @@ @interface ViewController ()
@implementation ViewController
-- (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view.
-}
-
-- (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
-}
-
- (void)persistenceReference {
// [START keep_synchronized]
FIRDatabaseReference *scoresRef = [[FIRDatabase database] referenceWithPath:@"scores"];
@@ -161,4 +153,28 @@ - (void)writeNewUserWithCompletion:(FIRUser *)user withName:(NSString *)username
// [END rtdb_write_new_user_completion]
}
+- (void)singleUseGetDataForUserId:(NSString *)uid {
+ FIRDatabaseReference *ref = [FIRDatabase database].reference;
+ // [START single_value_get_data]
+ NSString *userPath = [NSString stringWithFormat:@"users/%@/username", uid];
+ [[ref child:userPath] getDataWithCompletionBlock:^(NSError * _Nullable error, FIRDataSnapshot * _Nonnull snapshot) {
+ if (error) {
+ NSLog(@"Received an error %@", error);
+ return;
+ }
+ NSString *userName = snapshot.value;
+ }];
+ // [END single_value_get_data]
+}
+
+- (void)incrementStarsForPost:(NSString *)postID byUser: (NSString *) userID {
+ // [START rtdb_post_stars_increment]
+ NSDictionary *updates = @{[NSString stringWithFormat: @"posts/%@/stars/%@", postID, userID]: @TRUE,
+ [NSString stringWithFormat: @"posts/%@/starCount", postID]: [FIRServerValue increment:@1],
+ [NSString stringWithFormat: @"user-posts/%@/stars/%@", postID, userID]: @TRUE,
+ [NSString stringWithFormat: @"user-posts/%@/starCount", postID]: [FIRServerValue increment:@1]};
+ [[[FIRDatabase database] reference] updateChildValues:updates];
+ // [END rtdb_post_stars_increment]
+}
+
@end
diff --git a/database/DatabaseReference/swift/AppDelegate.swift b/database/DatabaseReference/swift/AppDelegate.swift
index a30a1b46..60171b17 100644
--- a/database/DatabaseReference/swift/AppDelegate.swift
+++ b/database/DatabaseReference/swift/AppDelegate.swift
@@ -16,7 +16,8 @@
import UIKit
-import Firebase
+import FirebaseCore
+import FirebaseDatabase
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -24,7 +25,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
diff --git a/database/DatabaseReference/swift/ViewController.swift b/database/DatabaseReference/swift/ViewController.swift
index 12cab099..84b6291f 100644
--- a/database/DatabaseReference/swift/ViewController.swift
+++ b/database/DatabaseReference/swift/ViewController.swift
@@ -16,22 +16,13 @@
import UIKit
-import Firebase
+import FirebaseAuth
+import FirebaseDatabase
class ViewController: UIViewController {
var ref: DatabaseReference!
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do any additional setup after loading the view, typically from a nib.
- }
-
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
-
func persistenceReference() {
// [START keep_synchronized]
let scoresRef = Database.database().reference(withPath: "scores")
@@ -103,39 +94,61 @@ class ViewController: UIViewController {
// [END clock_skew]
}
- func writeNewUser(_ user: Firebase.User, withUsername username: String) {
+ func writeNewUser(_ user: FirebaseAuth.User, withUsername username: String) {
// [START rtdb_write_new_user]
ref.child("users").child(user.uid).setValue(["username": username])
// [END rtdb_write_new_user]
}
- func writeNewUserWithCompletion(_ user: Firebase.User, withUsername username: String) {
+ func writeNewUserWithCompletion(_ user: FirebaseAuth.User, withUsername username: String) async {
// [START rtdb_write_new_user_completion]
- ref.child("users").child(user.uid).setValue(["username": username]) {
- (error:Error?, ref:DatabaseReference) in
- if let error = error {
- print("Data could not be saved: \(error).")
- } else {
- print("Data saved successfully!")
- }
+ do {
+ try await ref.child("users").child(user.uid).setValue(["username": username])
+ print("Data saved successfully!")
+ } catch {
+ print("Data could not be saved: \(error).")
}
// [END rtdb_write_new_user_completion]
}
- func emulatorSettings(Database: Database) {
- // [START rtdb_emulator_connect]
+ func singleUseFetchData(uid: String) async {
+ let ref = Database.database().reference()
+ // [START single_value_get_data]
+ do {
+ let snapshot = try await ref.child("users/\(uid)/username").getData()
+ let userName = snapshot.value as? String ?? "Unknown"
+ } catch {
+ print(error)
+ }
+ // [END single_value_get_data]
+ }
+
+ func emulatorSettings() {
+ // [START rtdb_emulator_connect]
// In almost all cases the ns (namespace) is your project ID.
- let db = Database.database(url:@"http://localhost:9000?ns=YOUR_DATABASE_NAMESPACE")
- // [END rtdb_emulator_connect]
+ let db = Database.database(url:"http://127.0.0.1:9000?ns=YOUR_DATABASE_NAMESPACE")
+ // [END rtdb_emulator_connect]
}
- func flushRealtimeDatabase(Database: Database) {
- // [START rtdb_emulator_flush]
+ func flushRealtimeDatabase() {
+ // [START rtdb_emulator_flush]
// With a DatabaseReference, write nil to clear the database.
- Database.database().reference().setValue(nil);
+ Database.database().reference().setValue(nil)
// [END rtdb_emulator_flush]
}
+ func incrementStars(forPost postID: String, byUser userID: String) {
+ // [START rtdb_post_stars_increment]
+ let updates = [
+ "posts/\(postID)/stars/\(userID)": true,
+ "posts/\(postID)/starCount": ServerValue.increment(1),
+ "user-posts/\(postID)/stars/\(userID)": true,
+ "user-posts/\(postID)/starCount": ServerValue.increment(1)
+ ] as [String : Any]
+ Database.database().reference().updateChildValues(updates)
+ // [END rtdb_post_stars_increment]
+ }
+
}
func combinedExample() {
@@ -151,7 +164,7 @@ func combinedExample() {
connectedRef.observe(.value, with: { snapshot in
// only handle connection established (or I've reconnected after a loss of connection)
- guard let connected = snapshot.value as? Bool, connected else { return }
+ guard snapshot.value as? Bool ?? false else { return }
// add this device to my connections list
let con = myConnectionsRef.childByAutoId()
diff --git a/database/Podfile b/database/Podfile
deleted file mode 100644
index cb4e2823..00000000
--- a/database/Podfile
+++ /dev/null
@@ -1,8 +0,0 @@
-# Firebase Database ReferenceCode
-use_frameworks!
-platform :ios, '7.0'
-pod 'Firebase/Database'
-pod 'Firebase/Auth'
-
-target 'DatabaseReference' do
-end
diff --git a/database/Podfile.lock b/database/Podfile.lock
deleted file mode 100644
index 57373b70..00000000
--- a/database/Podfile.lock
+++ /dev/null
@@ -1,77 +0,0 @@
-PODS:
- - Firebase/Auth (4.13.0):
- - Firebase/Core
- - FirebaseAuth (= 4.6.1)
- - Firebase/Core (4.13.0):
- - FirebaseAnalytics (= 4.2.0)
- - FirebaseCore (= 4.0.20)
- - Firebase/Database (4.13.0):
- - Firebase/Core
- - FirebaseDatabase (= 4.1.5)
- - FirebaseAnalytics (4.2.0):
- - FirebaseCore (~> 4.0)
- - FirebaseInstanceID (~> 2.0)
- - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- - nanopb (~> 0.3)
- - FirebaseAuth (4.6.1):
- - FirebaseAnalytics (~> 4.2)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- - GTMSessionFetcher/Core (~> 1.1)
- - FirebaseCore (4.0.20):
- - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- - FirebaseDatabase (4.1.5):
- - FirebaseAnalytics (~> 4.1)
- - FirebaseCore (~> 4.0)
- - leveldb-library (~> 1.18)
- - FirebaseInstanceID (2.0.10):
- - FirebaseCore (~> 4.0)
- - GoogleToolboxForMac/DebugUtils (2.1.4):
- - GoogleToolboxForMac/Defines (= 2.1.4)
- - GoogleToolboxForMac/Defines (2.1.4)
- - "GoogleToolboxForMac/NSData+zlib (2.1.4)":
- - GoogleToolboxForMac/Defines (= 2.1.4)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4)":
- - GoogleToolboxForMac/DebugUtils (= 2.1.4)
- - GoogleToolboxForMac/Defines (= 2.1.4)
- - "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
- - "GoogleToolboxForMac/NSString+URLArguments (2.1.4)"
- - GTMSessionFetcher/Core (1.2.2)
- - leveldb-library (1.22)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
-
-DEPENDENCIES:
- - Firebase/Auth
- - Firebase/Database
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - Firebase
- - FirebaseAnalytics
- - FirebaseAuth
- - FirebaseCore
- - FirebaseDatabase
- - FirebaseInstanceID
- - GoogleToolboxForMac
- - GTMSessionFetcher
- - leveldb-library
- - nanopb
-
-SPEC CHECKSUMS:
- Firebase: 5ec5e863d269d82d66b4bf56856726f8fb8f0fb3
- FirebaseAnalytics: 7ef69e76a5142f643aeb47c780e1cdce4e23632e
- FirebaseAuth: bf22cacf22c60ab454bf2636f556d8892b10b53f
- FirebaseCore: 90cb1c53d69b556f112a1bf72b5fcfaad7650790
- FirebaseDatabase: 5f0bc6134c5c237cf55f9e1249d406770a75eafd
- FirebaseInstanceID: 8d20d890d65c917f9f7d9950b6e10a760ad34321
- GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
-
-PODFILE CHECKSUM: 2d6d3f5d6efef8839436d4bcca6d595b46547d30
-
-COCOAPODS: 1.7.5
diff --git a/dl-invites-sample/InvitesSample/AppDelegate.swift b/dl-invites-sample/InvitesSample/AppDelegate.swift
index 3678f797..1f056d87 100644
--- a/dl-invites-sample/InvitesSample/AppDelegate.swift
+++ b/dl-invites-sample/InvitesSample/AppDelegate.swift
@@ -16,7 +16,7 @@
import UIKit
-import Firebase
+import FirebaseCore
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
diff --git a/dl-invites-sample/Podfile b/dl-invites-sample/Podfile
index 356db6a6..145c4968 100644
--- a/dl-invites-sample/Podfile
+++ b/dl-invites-sample/Podfile
@@ -5,7 +5,6 @@ target 'InvitesSample' do
use_frameworks!
pod 'Firebase/DynamicLinks'
- pod 'Firebase/Core'
target 'InvitesSampleTests' do
inherit! :search_paths
@@ -24,6 +23,5 @@ target 'InvitesSampleObjC' do
use_frameworks!
pod 'Firebase/DynamicLinks'
- pod 'Firebase/Core'
end
diff --git a/dl-invites-sample/Podfile.lock b/dl-invites-sample/Podfile.lock
index 4c43404a..a38be10b 100644
--- a/dl-invites-sample/Podfile.lock
+++ b/dl-invites-sample/Podfile.lock
@@ -1,109 +1,57 @@
PODS:
- - Firebase/Core (6.8.0):
+ - Firebase/CoreOnly (6.34.0):
+ - FirebaseCore (= 6.10.4)
+ - Firebase/DynamicLinks (6.34.0):
- Firebase/CoreOnly
- - FirebaseAnalytics (= 6.1.1)
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/DynamicLinks (6.8.0):
- - Firebase/CoreOnly
- - FirebaseDynamicLinks (~> 4.0.4)
- - FirebaseAnalytics (6.1.1):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
- - GoogleAppMeasurement (= 6.1.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - FirebaseAnalyticsInterop (1.4.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseDynamicLinks (4.0.4):
- - FirebaseAnalyticsInterop (~> 1.3)
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - GoogleAppMeasurement (6.1.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/AppDelegateSwizzler (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
+ - FirebaseDynamicLinks (~> 4.3.1)
+ - FirebaseCore (6.10.4):
+ - FirebaseCoreDiagnostics (~> 1.6)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/Logger (~> 6.7)
+ - FirebaseCoreDiagnostics (1.7.0):
+ - GoogleDataTransport (~> 7.4)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/Logger (~> 6.7)
+ - nanopb (~> 1.30906.0)
+ - FirebaseDynamicLinks (4.3.1):
+ - FirebaseCore (~> 6.10)
+ - GoogleDataTransport (7.5.1):
+ - nanopb (~> 1.30906.0)
+ - GoogleUtilities/Environment (6.7.2):
+ - PromisesObjC (~> 1.2)
+ - GoogleUtilities/Logger (6.7.2):
- GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (6.2.5):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.2.5)"
- - GoogleUtilities/Reachability (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.2.5):
- - GoogleUtilities/Logger
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
+ - nanopb (1.30906.0):
+ - nanopb/decode (= 1.30906.0)
+ - nanopb/encode (= 1.30906.0)
+ - nanopb/decode (1.30906.0)
+ - nanopb/encode (1.30906.0)
+ - PromisesObjC (1.2.12)
DEPENDENCIES:
- - Firebase/Core
- Firebase/DynamicLinks
SPEC REPOS:
- https://github.com/cocoapods/specs.git:
+ trunk:
- Firebase
- - FirebaseAnalytics
- - FirebaseAnalyticsInterop
- FirebaseCore
- FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- FirebaseDynamicLinks
- - FirebaseInstanceID
- - GoogleAppMeasurement
- GoogleDataTransport
- - GoogleDataTransportCCTSupport
- GoogleUtilities
- nanopb
+ - PromisesObjC
SPEC CHECKSUMS:
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
- FirebaseAnalyticsInterop: d48b6ab67bcf016a05e55b71fc39c61c0cb6b7f3
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseDynamicLinks: 585355f9de854b847059188bb845b7dceae18cd5
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
+ Firebase: c23a36d9e4cdf7877dfcba8dd0c58add66358999
+ FirebaseCore: d3a978a3cfa3240bf7e4ba7d137fdf5b22b628ec
+ FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1
+ FirebaseDynamicLinks: 6eac37d86910382eafb6315d952cc44c9e176094
+ GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
+ GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
+ nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
+ PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
-PODFILE CHECKSUM: ea2286f19740542810d85972377bee24b5e93a82
+PODFILE CHECKSUM: 7de02ed38e9465e2c05bb12085a971c35543c261
-COCOAPODS: 1.7.5
+COCOAPODS: 1.15.2
diff --git a/firestore/objc/Podfile b/firestore/objc/Podfile
deleted file mode 100644
index b939fbea..00000000
--- a/firestore/objc/Podfile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Uncomment the next line to define a global platform for your project
-# platform :ios, '9.0'
-
-target 'firestore-smoketest-objc' do
-
- use_frameworks!
-
- # Pods for firestore-smoketest
- pod 'Firebase/Core'
- pod 'Firebase/Auth'
- pod 'Firebase/Firestore'
-
- target 'firestore-smoketest-objcTests' do
- inherit! :search_paths
- # Pods for testing
- end
-
-end
diff --git a/firestore/objc/Podfile.lock b/firestore/objc/Podfile.lock
deleted file mode 100644
index 6fab61b5..00000000
--- a/firestore/objc/Podfile.lock
+++ /dev/null
@@ -1,170 +0,0 @@
-PODS:
- - BoringSSL-GRPC (0.0.3):
- - BoringSSL-GRPC/Implementation (= 0.0.3)
- - BoringSSL-GRPC/Interface (= 0.0.3)
- - BoringSSL-GRPC/Implementation (0.0.3):
- - BoringSSL-GRPC/Interface (= 0.0.3)
- - BoringSSL-GRPC/Interface (0.0.3)
- - Firebase/Auth (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAuth (~> 6.2.3)
- - Firebase/Core (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAnalytics (= 6.1.1)
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/Firestore (6.8.0):
- - Firebase/CoreOnly
- - FirebaseFirestore (~> 1.5.0)
- - FirebaseAnalytics (6.1.1):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
- - GoogleAppMeasurement (= 6.1.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - FirebaseAuth (6.2.3):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.2)
- - GoogleUtilities/Environment (~> 6.2)
- - GTMSessionFetcher/Core (~> 1.1)
- - FirebaseAuthInterop (1.0.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseFirestore (1.5.0):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - FirebaseFirestore/abseil-cpp (= 1.5.0)
- - "gRPC-C++ (= 0.0.9)"
- - leveldb-library (~> 1.22)
- - nanopb (~> 0.3.901)
- - Protobuf (~> 3.1)
- - FirebaseFirestore/abseil-cpp (1.5.0):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - "gRPC-C++ (= 0.0.9)"
- - leveldb-library (~> 1.22)
- - nanopb (~> 0.3.901)
- - Protobuf (~> 3.1)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - GoogleAppMeasurement (6.1.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/AppDelegateSwizzler (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (6.2.5):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.2.5)"
- - GoogleUtilities/Reachability (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.2.5):
- - GoogleUtilities/Logger
- - "gRPC-C++ (0.0.9)":
- - "gRPC-C++/Implementation (= 0.0.9)"
- - "gRPC-C++/Interface (= 0.0.9)"
- - "gRPC-C++/Implementation (0.0.9)":
- - "gRPC-C++/Interface (= 0.0.9)"
- - gRPC-Core (= 1.21.0)
- - nanopb (~> 0.3)
- - "gRPC-C++/Interface (0.0.9)"
- - gRPC-Core (1.21.0):
- - gRPC-Core/Implementation (= 1.21.0)
- - gRPC-Core/Interface (= 1.21.0)
- - gRPC-Core/Implementation (1.21.0):
- - BoringSSL-GRPC (= 0.0.3)
- - gRPC-Core/Interface (= 1.21.0)
- - nanopb (~> 0.3)
- - gRPC-Core/Interface (1.21.0)
- - GTMSessionFetcher/Core (1.2.2)
- - leveldb-library (1.22)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
- - Protobuf (3.9.0)
-
-DEPENDENCIES:
- - Firebase/Auth
- - Firebase/Core
- - Firebase/Firestore
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - BoringSSL-GRPC
- - Firebase
- - FirebaseAnalytics
- - FirebaseAuth
- - FirebaseAuthInterop
- - FirebaseCore
- - FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseFirestore
- - FirebaseInstanceID
- - GoogleAppMeasurement
- - GoogleDataTransport
- - GoogleDataTransportCCTSupport
- - GoogleUtilities
- - "gRPC-C++"
- - gRPC-Core
- - GTMSessionFetcher
- - leveldb-library
- - nanopb
- - Protobuf
-
-SPEC CHECKSUMS:
- BoringSSL-GRPC: db8764df3204ccea016e1c8dd15d9a9ad63ff318
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
- FirebaseAuth: e7f86c2dfc57281cd01f7da5e4b40e01e4510a4a
- FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseFirestore: c5873e279490fbe02239ab2cdfb91c2d546261cc
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- "gRPC-C++": 9dfe7b44821e7b3e44aacad2af29d2c21f7cde83
- gRPC-Core: c9aef9a261a1247e881b18059b84d597293c9947
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
- Protobuf: 1097ca58584c8d9be81bfbf2c5ff5975648dd87a
-
-PODFILE CHECKSUM: 6e8f8775e6e1f54c9a7ec4d1131f8b81f76c1a9c
-
-COCOAPODS: 1.7.5
diff --git a/firestore/objc/firestore-smoketest-objc.xcodeproj/project.pbxproj b/firestore/objc/firestore-smoketest-objc.xcodeproj/project.pbxproj
index 003801c2..2c8e8536 100644
--- a/firestore/objc/firestore-smoketest-objc.xcodeproj/project.pbxproj
+++ b/firestore/objc/firestore-smoketest-objc.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -18,6 +18,9 @@
8D70FC2A1F4CAE1B00C7F603 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8D70FC291F4CAE1B00C7F603 /* Assets.xcassets */; };
8D70FC2D1F4CAE1B00C7F603 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D70FC2B1F4CAE1B00C7F603 /* LaunchScreen.storyboard */; };
8D70FC381F4CAE1B00C7F603 /* firestore_smoketest_objcTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D70FC371F4CAE1B00C7F603 /* firestore_smoketest_objcTests.m */; };
+ 8D79519D2D28ABAD000FD694 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 8D79519C2D28ABAD000FD694 /* FirebaseAuth */; };
+ 8D79519F2D28ABAD000FD694 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D79519E2D28ABAD000FD694 /* FirebaseFirestore */; };
+ 8D9644E7260D565A002A46C9 /* FIRSolutionsBundleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D9644E6260D565A002A46C9 /* FIRSolutionsBundleViewController.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -51,6 +54,8 @@
8D70FC331F4CAE1B00C7F603 /* firestore-smoketest-objcTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "firestore-smoketest-objcTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
8D70FC371F4CAE1B00C7F603 /* firestore_smoketest_objcTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = firestore_smoketest_objcTests.m; sourceTree = ""; };
8D70FC391F4CAE1B00C7F603 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 8D9644E5260D565A002A46C9 /* FIRSolutionsBundleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FIRSolutionsBundleViewController.h; sourceTree = ""; };
+ 8D9644E6260D565A002A46C9 /* FIRSolutionsBundleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FIRSolutionsBundleViewController.m; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -58,6 +63,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D79519D2D28ABAD000FD694 /* FirebaseAuth in Frameworks */,
+ 8D79519F2D28ABAD000FD694 /* FirebaseFirestore in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -77,6 +84,7 @@
8D4F2EF1201162EE002ED308 /* GoogleService-Info.plist */,
8D70FC1C1F4CAE1B00C7F603 /* firestore-smoketest-objc */,
8D70FC361F4CAE1B00C7F603 /* firestore-smoketest-objcTests */,
+ 8D79519B2D28ABAD000FD694 /* Frameworks */,
8D70FC1B1F4CAE1B00C7F603 /* Products */,
);
sourceTree = "";
@@ -103,6 +111,8 @@
8D669A7420F423B200F08512 /* FIRSolutionCountersViewController.m */,
8D669A7620F423B200F08512 /* FIRSolutionArraysViewController.h */,
8D669A7520F423B200F08512 /* FIRSolutionArraysViewController.m */,
+ 8D9644E5260D565A002A46C9 /* FIRSolutionsBundleViewController.h */,
+ 8D9644E6260D565A002A46C9 /* FIRSolutionsBundleViewController.m */,
8D70FC261F4CAE1B00C7F603 /* Main.storyboard */,
8D70FC291F4CAE1B00C7F603 /* Assets.xcassets */,
8D70FC2B1F4CAE1B00C7F603 /* LaunchScreen.storyboard */,
@@ -129,6 +139,13 @@
path = "firestore-smoketest-objcTests";
sourceTree = "";
};
+ 8D79519B2D28ABAD000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -173,7 +190,7 @@
8D70FC121F4CAE1B00C7F603 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0830;
+ LastUpgradeCheck = 1110;
ORGANIZATIONNAME = Firebase;
TargetAttributes = {
8D70FC191F4CAE1B00C7F603 = {
@@ -189,13 +206,16 @@
};
buildConfigurationList = 8D70FC151F4CAE1B00C7F603 /* Build configuration list for PBXProject "firestore-smoketest-objc" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 8D70FC111F4CAE1B00C7F603;
+ packageReferences = (
+ 8D79519A2D28AB9C000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
productRefGroup = 8D70FC1B1F4CAE1B00C7F603 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -238,6 +258,7 @@
8D669A7B20F423B200F08512 /* FIRSolutionArraysViewController.m in Sources */,
8D669A7A20F423B200F08512 /* FIRSolutionCountersViewController.m in Sources */,
8D70FC1F1F4CAE1B00C7F603 /* main.m in Sources */,
+ 8D9644E7260D565A002A46C9 /* FIRSolutionsBundleViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -283,21 +304,30 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -332,21 +362,30 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -376,7 +415,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = "firestore-smoketest-objc/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.firebase.firestore-smoketest-objc";
PRODUCT_NAME = "$(TARGET_NAME)";
};
@@ -387,7 +429,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = "firestore-smoketest-objc/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.firebase.firestore-smoketest-objc";
PRODUCT_NAME = "$(TARGET_NAME)";
};
@@ -398,7 +443,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = "firestore-smoketest-objcTests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.firebase.firestore-smoketest-objcTests";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/firestore-smoketest-objc.app/firestore-smoketest-objc";
@@ -410,7 +459,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = "firestore-smoketest-objcTests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.firebase.firestore-smoketest-objcTests";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/firestore-smoketest-objc.app/firestore-smoketest-objc";
@@ -448,6 +501,30 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D79519A2D28AB9C000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D79519C2D28ABAD000FD694 /* FirebaseAuth */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D79519A2D28AB9C000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAuth;
+ };
+ 8D79519E2D28ABAD000FD694 /* FirebaseFirestore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D79519A2D28AB9C000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFirestore;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 8D70FC121F4CAE1B00C7F603 /* Project object */;
}
diff --git a/firestore/objc/firestore-smoketest-objc/AppDelegate.m b/firestore/objc/firestore-smoketest-objc/AppDelegate.m
index c24d8c25..cf614966 100644
--- a/firestore/objc/firestore-smoketest-objc/AppDelegate.m
+++ b/firestore/objc/firestore-smoketest-objc/AppDelegate.m
@@ -16,7 +16,8 @@
#import "AppDelegate.h"
-@import Firebase;
+@import FirebaseCore;
+@import FirebaseFirestore;
@interface AppDelegate ()
diff --git a/firestore/objc/firestore-smoketest-objc/FIRSolutionAggregationViewController.m b/firestore/objc/firestore-smoketest-objc/FIRSolutionAggregationViewController.m
index e0b45df2..0ce39f68 100644
--- a/firestore/objc/firestore-smoketest-objc/FIRSolutionAggregationViewController.m
+++ b/firestore/objc/firestore-smoketest-objc/FIRSolutionAggregationViewController.m
@@ -14,7 +14,7 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseFirestore;
#import "FIRSolutionAggregationViewController.h"
diff --git a/firestore/objc/firestore-smoketest-objc/FIRSolutionArraysViewController.m b/firestore/objc/firestore-smoketest-objc/FIRSolutionArraysViewController.m
index a36a7831..9671a517 100644
--- a/firestore/objc/firestore-smoketest-objc/FIRSolutionArraysViewController.m
+++ b/firestore/objc/firestore-smoketest-objc/FIRSolutionArraysViewController.m
@@ -14,7 +14,7 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseFirestore;
#import "FIRSolutionArraysViewController.h"
diff --git a/firestore/objc/firestore-smoketest-objc/FIRSolutionCountersViewController.m b/firestore/objc/firestore-smoketest-objc/FIRSolutionCountersViewController.m
index 34cbfd52..2e788385 100644
--- a/firestore/objc/firestore-smoketest-objc/FIRSolutionCountersViewController.m
+++ b/firestore/objc/firestore-smoketest-objc/FIRSolutionCountersViewController.m
@@ -14,7 +14,7 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseFirestore;
#import "FIRSolutionCountersViewController.h"
diff --git a/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.h b/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.h
new file mode 100644
index 00000000..daef62ef
--- /dev/null
+++ b/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2021 Google LLC
+//
+// 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRSolutionsBundleViewController : UIViewController
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.m b/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.m
new file mode 100644
index 00000000..2e3efe55
--- /dev/null
+++ b/firestore/objc/firestore-smoketest-objc/FIRSolutionsBundleViewController.m
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2021 Google LLC
+//
+// 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 FirebaseFirestore;
+
+#import "FIRSolutionsBundleViewController.h"
+
+@interface FIRSolutionsBundleViewController ()
+
+@end
+
+@implementation FIRSolutionsBundleViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+// [START fs_bundle_load]
+// Utility function for errors when loading bundles.
+- (NSError *)bundleLoadErrorWithReason:(NSString *)reason {
+ return [NSError errorWithDomain:@"FIRSampleErrorDomain"
+ code:0
+ userInfo:@{NSLocalizedFailureReasonErrorKey: reason}];
+}
+
+// Loads a remote bundle from the provided url.
+- (void)fetchRemoteBundleForFirestore:(FIRFirestore *)firestore
+ fromURL:(NSURL *)url
+ completion:(void (^)(FIRLoadBundleTaskProgress *_Nullable,
+ NSError *_Nullable))completion {
+ NSInputStream *inputStream = [NSInputStream inputStreamWithURL:url];
+ if (inputStream == nil) {
+ // Unable to create input stream.
+ NSError *error =
+ [self bundleLoadErrorWithReason:
+ [NSString stringWithFormat:@"Unable to create stream from the given url: %@", url]];
+ completion(nil, error);
+ return;
+ }
+
+ [firestore loadBundleStream:inputStream
+ completion:^(FIRLoadBundleTaskProgress * _Nullable progress,
+ NSError * _Nullable error) {
+ if (progress == nil) {
+ completion(nil, error);
+ return;
+ }
+
+ if (progress.state == FIRLoadBundleTaskStateSuccess) {
+ completion(progress, nil);
+ } else {
+ NSError *concreteError =
+ [self bundleLoadErrorWithReason:
+ [NSString stringWithFormat:
+ @"Expected bundle load to be completed, but got %ld instead",
+ (long)progress.state]];
+ completion(nil, concreteError);
+ }
+ completion(nil, nil);
+ }];
+}
+
+// Loads a bundled query.
+- (void)loadQueryNamed:(NSString *)queryName
+ fromRemoteBundleURL:(NSURL *)url
+ withFirestore:(FIRFirestore *)firestore
+ completion:(void (^)(FIRQuery *_Nullable, NSError *_Nullable))completion {
+ [self fetchRemoteBundleForFirestore:firestore
+ fromURL:url
+ completion:^(FIRLoadBundleTaskProgress *progress, NSError *error) {
+ if (error != nil) {
+ completion(nil, error);
+ return;
+ }
+
+ [firestore getQueryNamed:queryName completion:^(FIRQuery *query) {
+ if (query == nil) {
+ NSString *errorReason =
+ [NSString stringWithFormat:@"Could not find query named %@", queryName];
+ NSError *error = [self bundleLoadErrorWithReason:errorReason];
+ completion(nil, error);
+ return;
+ }
+ completion(query, nil);
+ }];
+ }];
+}
+
+- (void)runStoriesQuery {
+ NSString *queryName = @"latest-stories-query";
+ FIRFirestore *firestore = [FIRFirestore firestore];
+ NSURL *bundleURL = [NSURL URLWithString:@"https://example.com/createBundle"];
+ [self loadQueryNamed:queryName
+ fromRemoteBundleURL:bundleURL
+ withFirestore:firestore
+ completion:^(FIRQuery *query, NSError *error) {
+ // Handle query results
+ }];
+}
+// [END fs_bundle_load]
+
+// [START fs_simple_bundle_load]
+// Load a bundle from a local URL.
+- (void)loadBundleFromBundleURL:(NSURL *)bundleURL {
+ FIRFirestore *firestore = [FIRFirestore firestore];
+ NSError *error;
+ NSData *data = [NSData dataWithContentsOfURL:bundleURL options:kNilOptions error:&error];
+ if (error != nil) {
+ NSLog(@"%@", error);
+ return;
+ }
+ [firestore loadBundle:data];
+}
+// [END fs_simple_bundle_load]
+
+// [START fs_named_query]
+- (void)runNamedQuery {
+ FIRFirestore *firestore = [FIRFirestore firestore];
+ [firestore getQueryNamed:@"coll-query" completion:^(FIRQuery *_Nullable query) {
+ [query getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ // ...
+ }];
+ }];
+}
+// [END fs_named_query]
+
+// [START bundle_observe_progress]
+- (void)observeProgressOfLoadBundleTask:(FIRLoadBundleTask *)loadBundleTask {
+ NSInteger handle = [loadBundleTask addObserver:^(FIRLoadBundleTaskProgress *progress) {
+ NSLog(@"Loaded %ld bytes out of %ld total",
+ (long)progress.bytesLoaded,
+ (long)progress.totalBytes);
+ }];
+
+ // ...
+ [loadBundleTask removeObserverWithHandle:handle];
+}
+// [END bundle_observe_progress]
+
+@end
diff --git a/firestore/objc/firestore-smoketest-objc/ViewController.m b/firestore/objc/firestore-smoketest-objc/ViewController.m
index 68c50774..977c25d5 100644
--- a/firestore/objc/firestore-smoketest-objc/ViewController.m
+++ b/firestore/objc/firestore-smoketest-objc/ViewController.m
@@ -80,7 +80,9 @@ - (void)viewDidLoad {
- (void)setupCacheSize {
// [START fs_setup_cache]
FIRFirestoreSettings *settings = [FIRFirestore firestore].settings;
- settings.cacheSizeBytes = kFIRFirestoreCacheSizeUnlimited;
+ // Set cache size to 100 MB
+ settings.cacheSettings =
+ [[FIRPersistentCacheSettings alloc] initWithSizeBytes:@(100 * 1024 * 1024)];
[FIRFirestore firestore].settings = settings;
// [END fs_setup_cache]
}
@@ -756,6 +758,21 @@ - (void)getMultipleAll {
// [END get_multiple_all]
}
+- (void)getMultipleAllSubcollection {
+ // [START get_multiple_all_subcollection]
+ [[self.db collectionWithPath:@"cities/SF/landmarks"]
+ getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error getting documents: %@", error);
+ } else {
+ for (FIRDocumentSnapshot *document in snapshot.documents) {
+ NSLog(@"%@ => %@", document.documentID, document.data);
+ }
+ }
+ }];
+ // [END get_multiple_all_subcollection]
+}
+
- (void)listenMultiple {
// [START listen_multiple]
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"]
@@ -852,15 +869,18 @@ - (void)simpleQueries {
// Create a query against the collection.
FIRQuery *query = [citiesRef queryWhereField:@"state" isEqualTo:@"CA"];
// [END simple_queries]
+ // [START simple_query_not_equal]
+ query = [citiesRef queryWhereField:@"capital" isNotEqualTo:@NO];
+ // [END simple_query_not_equal]
NSLog(@"%@", query);
}
- (void)exampleFilters {
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"];
// [START example_filters]
- [citiesRef queryWhereField:@"state" isEqualTo:@"CA"];
- [citiesRef queryWhereField:@"population" isLessThan:@100000];
- [citiesRef queryWhereField:@"name" isGreaterThanOrEqualTo:@"San Francisco"];
+ FIRQuery *stateQuery = [citiesRef queryWhereField:@"state" isEqualTo:@"CA"];
+ FIRQuery *populationQuery = [citiesRef queryWhereField:@"population" isLessThan:@100000];
+ FIRQuery *nameQuery = [citiesRef queryWhereField:@"name" isGreaterThanOrEqualTo:@"San Francisco"];
// [END example_filters]
}
@@ -872,7 +892,7 @@ - (void)onlyCapitals {
NSLog(@"%@", capitalCities);
}
--(void)arrayContainsFilter {
+- (void)arrayContainsFilter {
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"];
// [START array_contains_filter]
[citiesRef queryWhereField:@"state" arrayContains:@"west_coast"];
@@ -952,6 +972,30 @@ - (void)invalidFilterAndOrder {
// [END invalid_filter_and_order]
}
+- (void)arrayContainsAnyQueries {
+ // [START array_contains_any_filter]
+ FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"];
+
+ [citiesRef queryWhereField:@"regions" arrayContainsAny:@[@"west_coast", @"east_coast"]];
+ // [END array_contains_any_filter]
+}
+
+- (void)inQueries {
+ // [START in_filter]
+ FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"];
+
+ [citiesRef queryWhereField:@"country" in:@[@"USA", @"Japan"]];
+ // [END in_filter]
+
+ // [START in_filter_with_array]
+ [citiesRef queryWhereField:@"regions" in:@[@[@"west_coast"], @[@"east_coast"]]];
+ // [END in_filter_with_array]
+
+ // [START not_in_filter]
+ [citiesRef queryWhereField:@"country" notIn:@[@"USA", @"Japan"]];
+ // [END not_in_filter]
+}
+
// =======================================================================================
// ====== https://firebase.google.com/preview/firestore/client/enable-offline ============
// =======================================================================================
@@ -959,7 +1003,15 @@ - (void)invalidFilterAndOrder {
- (void)enableOffline {
// [START enable_offline]
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];
- settings.persistenceEnabled = YES;
+
+ // Use memory-only cache
+ settings.cacheSettings = [[FIRMemoryCacheSettings alloc]
+ initWithGarbageCollectorSettings:[[FIRMemoryLRUGCSettings alloc] init]];
+
+ // Use persistent disk cache (default behavior)
+ // This example uses 100 MB.
+ settings.cacheSettings = [[FIRPersistentCacheSettings alloc]
+ initWithSizeBytes:@(100 * 1024 * 1024)];
// Any additional options
// ...
@@ -1115,4 +1167,218 @@ - (void)emulatorSettings {
// [END fs_emulator_connect]
}
+- (void)countAggregateCollection {
+ // [START count_aggregate_collection]
+ FIRCollectionReference *query = [self.db collectionWithPath:@"cities"];
+ [query.count aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching count: %@", error);
+ } else {
+ NSLog(@"Cities count: %@", snapshot.count);
+ }
+ }];
+ // [END count_aggregate_collection]
+}
+
+- (void)countAggregateQuery {
+ // [START count_aggregate_query]
+ FIRQuery *query =
+ [[self.db collectionWithPath:@"cities"]
+ queryWhereField:@"state"
+ isEqualTo:@"CA"];
+ [query.count aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching count: %@", error);
+ } else {
+ NSLog(@"Cities count: %@", snapshot.count);
+ }
+ }];
+ // [END count_aggregate_query]
+}
+
+- (void)sumAggregateCollection {
+ // [START sum_aggregate_collection]
+ FIRQuery *query = [self.db collectionWithPath:@"cities"];
+ FIRAggregateQuery *aggregateQuery = [query aggregate:@[
+ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]];
+ [aggregateQuery aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching aggregate: %@", error);
+ } else {
+ NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
+ }
+ }];
+ // [END sum_aggregate_collection]
+}
+
+- (void)sumAggregateQuery {
+ // [START sum_aggregate_query]
+ FIRQuery *query = [[self.db collectionWithPath:@"cities"]
+ queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]];
+ FIRAggregateQuery *aggregateQuery = [query aggregate:@[
+ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]];
+ [aggregateQuery aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching aggregate: %@", error);
+ } else {
+ NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
+ }
+ }];
+ // [END sum_aggregate_query]
+}
+
+- (void)averageAggregateCollection {
+ // [START average_aggregate_collection]
+ FIRQuery *query = [self.db collectionWithPath:@"cities"];
+ FIRAggregateQuery *aggregateQuery = [query aggregate:@[
+ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
+ [aggregateQuery aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching aggregate: %@", error);
+ } else {
+ NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
+ }
+ }];
+ // [END average_aggregate_collection]
+}
+
+- (void)averageAggregateQuery {
+ // [START average_aggregate_query]
+ FIRQuery *query = [[self.db collectionWithPath:@"cities"]
+ queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]];
+ FIRAggregateQuery *aggregateQuery = [query aggregate:@[
+ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
+ [aggregateQuery aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching aggregate: %@", error);
+ } else {
+ NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
+ }
+ }];
+ // [END average_aggregate_query]
+}
+
+- (void)multiAggregateCollection {
+ // [START multi_aggregate_collection]
+ FIRQuery *query = [self.db collectionWithPath:@"cities"];
+ FIRAggregateQuery *aggregateQuery = [query aggregate:@[
+ [FIRAggregateField aggregateFieldForCount],
+ [FIRAggregateField aggregateFieldForSumOfField:@"population"],
+ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
+ [aggregateQuery aggregationWithSource:FIRAggregateSourceServer
+ completion:^(FIRAggregateQuerySnapshot *snapshot,
+ NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching aggregate: %@", error);
+ } else {
+ NSLog(@"Count: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]]);
+ NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
+ NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
+ }
+ }];
+ // [END multi_aggregate_collection]
+}
+
+- (void)orQuery {
+ // [START or_query]
+ FIRCollectionReference *collection = [self.db collectionWithPath:@"cities"];
+ FIRQuery *query = [collection queryWhereFilter:[FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"state" isEqualTo:@"CA"],
+ [FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"capital" isEqualTo:@YES],
+ [FIRFilter filterWhereField:@"population" isGreaterThanOrEqualTo:@1000000]
+ ]]
+ ]]];
+ // [END or_query]
+}
+
+- (void)orQueryDisjunctions {
+ FIRCollectionReference *collection = [self.db collectionWithPath:@"cities"];
+
+ // [START one_disjunction]
+ [collection queryWhereField:@"a" isEqualTo:@1];
+ // [END one_disjunction]
+
+ // [START two_disjunctions]
+ [collection queryWhereFilter:[FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" isEqualTo:@1],
+ [FIRFilter filterWhereField:@"b" isEqualTo:@2]
+ ]]];
+ // [END two_disjunctions]
+
+ // [START four_disjunctions]
+ [collection queryWhereFilter:[FIRFilter orFilterWithFilters:@[
+ [FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" isEqualTo:@1],
+ [FIRFilter filterWhereField:@"c" isEqualTo:@3]
+ ]],
+ [FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" isEqualTo:@1],
+ [FIRFilter filterWhereField:@"d" isEqualTo:@4]
+ ]],
+ [FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"b" isEqualTo:@2],
+ [FIRFilter filterWhereField:@"c" isEqualTo:@3]
+ ]],
+ [FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"b" isEqualTo:@2],
+ [FIRFilter filterWhereField:@"d" isEqualTo:@4]
+ ]],
+ ]]];
+ // [END four_disjunctions]
+
+ // [START four_disjunctions_compact]
+ [collection queryWhereFilter:[FIRFilter andFilterWithFilters:@[
+ [FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" isEqualTo:@1],
+ [FIRFilter filterWhereField:@"b" isEqualTo:@2]
+ ]],
+ [FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"c" isEqualTo:@3],
+ [FIRFilter filterWhereField:@"d" isEqualTo:@4]
+ ]]
+ ]]];
+ // [END four_disjunctions_compact]
+
+ // [START 20_disjunctions]
+ [collection queryWhereFilter:[FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" in:@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10]],
+ [FIRFilter filterWhereField:@"b" in:@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10]]
+ ]]];
+ // [END 20_disjunctions]
+
+ // [START 10_disjunctions]
+ [collection queryWhereFilter:[FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" in: @[@1, @2, @3, @4, @5]],
+ [FIRFilter orFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"b" isEqualTo:@2],
+ [FIRFilter filterWhereField:@"c" isEqualTo:@3]
+ ]]
+ ]]];
+ // [END 10_disjunctions]
+}
+
+- (void)illegalDisjunctions {
+ FIRCollectionReference *collection = [self.db collectionWithPath:@"cities"];
+
+ // [START 20_disjunctions]
+ [collection queryWhereFilter:[FIRFilter andFilterWithFilters:@[
+ [FIRFilter filterWhereField:@"a" in:@[@1, @2, @3, @4, @5]],
+ [FIRFilter filterWhereField:@"b" in:@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10]]
+ ]]];
+ // [END 20_disjunctions]
+}
+
@end
diff --git a/firestore/swift/Podfile b/firestore/swift/Podfile
index a0a674fa..5acf781b 100644
--- a/firestore/swift/Podfile
+++ b/firestore/swift/Podfile
@@ -1,15 +1,19 @@
-# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+# No longer used since the project migrated to SPM, but this file still exists
+# for the GeoFire snippet below.
+platform :ios, '14.0'
target 'firestore-smoketest' do
# Comment this line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for firestore-smoketest
- pod 'Firebase/Core'
pod 'Firebase/Auth'
pod 'Firebase/Firestore'
+ # [START geofire_pod]
+ pod 'GeoFire/Utils'
+ # [END geofire_pod]
+
target 'firestore-smoketestTests' do
inherit! :search_paths
# Pods for testing
diff --git a/firestore/swift/Podfile.lock b/firestore/swift/Podfile.lock
deleted file mode 100644
index 540ef514..00000000
--- a/firestore/swift/Podfile.lock
+++ /dev/null
@@ -1,170 +0,0 @@
-PODS:
- - BoringSSL-GRPC (0.0.3):
- - BoringSSL-GRPC/Implementation (= 0.0.3)
- - BoringSSL-GRPC/Interface (= 0.0.3)
- - BoringSSL-GRPC/Implementation (0.0.3):
- - BoringSSL-GRPC/Interface (= 0.0.3)
- - BoringSSL-GRPC/Interface (0.0.3)
- - Firebase/Auth (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAuth (~> 6.2.3)
- - Firebase/Core (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAnalytics (= 6.1.1)
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/Firestore (6.8.0):
- - Firebase/CoreOnly
- - FirebaseFirestore (~> 1.5.0)
- - FirebaseAnalytics (6.1.1):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
- - GoogleAppMeasurement (= 6.1.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - FirebaseAuth (6.2.3):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.2)
- - GoogleUtilities/Environment (~> 6.2)
- - GTMSessionFetcher/Core (~> 1.1)
- - FirebaseAuthInterop (1.0.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseFirestore (1.5.0):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - FirebaseFirestore/abseil-cpp (= 1.5.0)
- - "gRPC-C++ (= 0.0.9)"
- - leveldb-library (~> 1.22)
- - nanopb (~> 0.3.901)
- - Protobuf (~> 3.1)
- - FirebaseFirestore/abseil-cpp (1.5.0):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.2)
- - "gRPC-C++ (= 0.0.9)"
- - leveldb-library (~> 1.22)
- - nanopb (~> 0.3.901)
- - Protobuf (~> 3.1)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - GoogleAppMeasurement (6.1.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/AppDelegateSwizzler (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (6.2.5):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.2.5)"
- - GoogleUtilities/Reachability (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.2.5):
- - GoogleUtilities/Logger
- - "gRPC-C++ (0.0.9)":
- - "gRPC-C++/Implementation (= 0.0.9)"
- - "gRPC-C++/Interface (= 0.0.9)"
- - "gRPC-C++/Implementation (0.0.9)":
- - "gRPC-C++/Interface (= 0.0.9)"
- - gRPC-Core (= 1.21.0)
- - nanopb (~> 0.3)
- - "gRPC-C++/Interface (0.0.9)"
- - gRPC-Core (1.21.0):
- - gRPC-Core/Implementation (= 1.21.0)
- - gRPC-Core/Interface (= 1.21.0)
- - gRPC-Core/Implementation (1.21.0):
- - BoringSSL-GRPC (= 0.0.3)
- - gRPC-Core/Interface (= 1.21.0)
- - nanopb (~> 0.3)
- - gRPC-Core/Interface (1.21.0)
- - GTMSessionFetcher/Core (1.2.2)
- - leveldb-library (1.22)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
- - Protobuf (3.9.0)
-
-DEPENDENCIES:
- - Firebase/Auth
- - Firebase/Core
- - Firebase/Firestore
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - BoringSSL-GRPC
- - Firebase
- - FirebaseAnalytics
- - FirebaseAuth
- - FirebaseAuthInterop
- - FirebaseCore
- - FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseFirestore
- - FirebaseInstanceID
- - GoogleAppMeasurement
- - GoogleDataTransport
- - GoogleDataTransportCCTSupport
- - GoogleUtilities
- - "gRPC-C++"
- - gRPC-Core
- - GTMSessionFetcher
- - leveldb-library
- - nanopb
- - Protobuf
-
-SPEC CHECKSUMS:
- BoringSSL-GRPC: db8764df3204ccea016e1c8dd15d9a9ad63ff318
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
- FirebaseAuth: e7f86c2dfc57281cd01f7da5e4b40e01e4510a4a
- FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseFirestore: c5873e279490fbe02239ab2cdfb91c2d546261cc
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- "gRPC-C++": 9dfe7b44821e7b3e44aacad2af29d2c21f7cde83
- gRPC-Core: c9aef9a261a1247e881b18059b84d597293c9947
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
- Protobuf: 1097ca58584c8d9be81bfbf2c5ff5975648dd87a
-
-PODFILE CHECKSUM: 67831f10b93a19c58541fb5f3fa7845a32fd6ca9
-
-COCOAPODS: 1.7.5
diff --git a/firestore/swift/firestore-smoketest.xcodeproj/project.pbxproj b/firestore/swift/firestore-smoketest.xcodeproj/project.pbxproj
index c4fa8dbe..90eb7522 100644
--- a/firestore/swift/firestore-smoketest.xcodeproj/project.pbxproj
+++ b/firestore/swift/firestore-smoketest.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 60;
objects = {
/* Begin PBXBuildFile section */
@@ -17,6 +17,14 @@
3EABFB2D1E254C8F00F4BBED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3EABFB2B1E254C8F00F4BBED /* LaunchScreen.storyboard */; };
3EABFB381E254C8F00F4BBED /* firestore_smoketestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EABFB371E254C8F00F4BBED /* firestore_smoketestTests.swift */; };
3EABFB431E254C8F00F4BBED /* firestore_smoketestUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EABFB421E254C8F00F4BBED /* firestore_smoketestUITests.swift */; };
+ 8D15627E2EA0474400D3B017 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 8D15627D2EA0474400D3B017 /* FirebaseAuth */; };
+ 8D1562802EA0474400D3B017 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D15627F2EA0474400D3B017 /* FirebaseFirestore */; };
+ 8D7951A32D28AC82000FD694 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951A22D28AC82000FD694 /* FirebaseAuth */; };
+ 8D7951A52D28AC82000FD694 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951A42D28AC82000FD694 /* FirebaseFirestore */; };
+ 8D7951A82D28ADBE000FD694 /* GeoFireUtils in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951A72D28ADBE000FD694 /* GeoFireUtils */; };
+ 8D7C36932EA069B70083BAF5 /* PipelineSnippets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D7C36922EA069B00083BAF5 /* PipelineSnippets.swift */; };
+ 8D864B17260D3947008E85B3 /* SolutionBundles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D864B16260D3947008E85B3 /* SolutionBundles.swift */; };
+ 8D864B35260D55C1008E85B3 /* SolutionGeoPointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DFC116F258A2B8E00D080CB /* SolutionGeoPointViewController.swift */; };
8DA9B4AB201165C800EC29CD /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8DA9B4AA201165C800EC29CD /* GoogleService-Info.plist */; };
/* End PBXBuildFile section */
@@ -54,7 +62,10 @@
3EABFB3E1E254C8F00F4BBED /* firestore-smoketestUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "firestore-smoketestUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
3EABFB421E254C8F00F4BBED /* firestore_smoketestUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = firestore_smoketestUITests.swift; sourceTree = ""; };
3EABFB441E254C8F00F4BBED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 8D7C36922EA069B00083BAF5 /* PipelineSnippets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineSnippets.swift; sourceTree = ""; };
+ 8D864B16260D3947008E85B3 /* SolutionBundles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolutionBundles.swift; sourceTree = ""; };
8DA9B4AA201165C800EC29CD /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 8DFC116F258A2B8E00D080CB /* SolutionGeoPointViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolutionGeoPointViewController.swift; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -62,6 +73,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D7951A32D28AC82000FD694 /* FirebaseAuth in Frameworks */,
+ 8D7951A82D28ADBE000FD694 /* GeoFireUtils in Frameworks */,
+ 8D7951A52D28AC82000FD694 /* FirebaseFirestore in Frameworks */,
+ 8D1562802EA0474400D3B017 /* FirebaseFirestore in Frameworks */,
+ 8D15627E2EA0474400D3B017 /* FirebaseAuth in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -88,6 +104,7 @@
3EABFB211E254C8F00F4BBED /* firestore-smoketest */,
3EABFB361E254C8F00F4BBED /* firestore-smoketestTests */,
3EABFB411E254C8F00F4BBED /* firestore-smoketestUITests */,
+ 8D7951A12D28AC82000FD694 /* Frameworks */,
3EABFB201E254C8F00F4BBED /* Products */,
);
sourceTree = "";
@@ -105,6 +122,7 @@
3EABFB211E254C8F00F4BBED /* firestore-smoketest */ = {
isa = PBXGroup;
children = (
+ 8D7C36922EA069B00083BAF5 /* PipelineSnippets.swift */,
8DA9B4AA201165C800EC29CD /* GoogleService-Info.plist */,
3EABFB221E254C8F00F4BBED /* AppDelegate.swift */,
3EABFB241E254C8F00F4BBED /* ViewController.swift */,
@@ -115,6 +133,8 @@
3E3694B41EFDB0F2009C9125 /* SolutionArraysViewController.swift */,
3E3694B61EFDB3BF009C9125 /* SolutionAggregationViewController.swift */,
3E3694B81EFDC039009C9125 /* SolutionCountersViewController.swift */,
+ 8DFC116F258A2B8E00D080CB /* SolutionGeoPointViewController.swift */,
+ 8D864B16260D3947008E85B3 /* SolutionBundles.swift */,
);
path = "firestore-smoketest";
sourceTree = "";
@@ -137,6 +157,13 @@
path = "firestore-smoketestUITests";
sourceTree = "";
};
+ 8D7951A12D28AC82000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -199,8 +226,9 @@
3EABFB171E254C8E00F4BBED /* Project object */ = {
isa = PBXProject;
attributes = {
+ BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0800;
- LastUpgradeCheck = 1000;
+ LastUpgradeCheck = 1610;
ORGANIZATIONNAME = Firebase;
TargetAttributes = {
3EABFB1E1E254C8E00F4BBED = {
@@ -224,13 +252,17 @@
};
buildConfigurationList = 3EABFB1A1E254C8E00F4BBED /* Build configuration list for PBXProject "firestore-smoketest" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 3EABFB161E254C8E00F4BBED;
+ packageReferences = (
+ 8D7951A62D28ADAE000FD694 /* XCRemoteSwiftPackageReference "geofire-objc" */,
+ 8D15627C2EA0474400D3B017 /* XCLocalSwiftPackageReference "../../../firebase-ios-sdk" */,
+ );
productRefGroup = 3EABFB201E254C8F00F4BBED /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -277,7 +309,10 @@
files = (
3EABFB251E254C8F00F4BBED /* ViewController.swift in Sources */,
3E3694B51EFDB0F2009C9125 /* SolutionArraysViewController.swift in Sources */,
+ 8D864B17260D3947008E85B3 /* SolutionBundles.swift in Sources */,
3E3694B71EFDB3BF009C9125 /* SolutionAggregationViewController.swift in Sources */,
+ 8D864B35260D55C1008E85B3 /* SolutionGeoPointViewController.swift in Sources */,
+ 8D7C36932EA069B70083BAF5 /* PipelineSnippets.swift in Sources */,
3EABFB231E254C8F00F4BBED /* AppDelegate.swift in Sources */,
3E3694B91EFDC039009C9125 /* SolutionCountersViewController.swift in Sources */,
);
@@ -358,6 +393,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -369,6 +405,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -383,12 +420,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 16.6;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -417,6 +455,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -428,6 +467,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -436,10 +476,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 16.6;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -451,11 +493,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
"GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = YES;
INFOPLIST_FILE = "firestore-smoketest/Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 10.3;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 16.6;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketest";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
@@ -466,11 +511,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
"GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = YES;
INFOPLIST_FILE = "firestore-smoketest/Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 10.3;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 16.6;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketest";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
@@ -478,10 +526,13 @@
3EABFB4B1E254C8F00F4BBED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = "firestore-smoketestTests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketestTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
@@ -492,10 +543,13 @@
3EABFB4C1E254C8F00F4BBED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = "firestore-smoketestTests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketestTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
@@ -506,9 +560,12 @@
3EABFB4E1E254C8F00F4BBED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
INFOPLIST_FILE = "firestore-smoketestUITests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketestUITests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
@@ -519,9 +576,12 @@
3EABFB4F1E254C8F00F4BBED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
INFOPLIST_FILE = "firestore-smoketestUITests/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = "com.google.firebase.firestore-smoketestUITests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
@@ -569,6 +629,58 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCLocalSwiftPackageReference section */
+ 8D15627C2EA0474400D3B017 /* XCLocalSwiftPackageReference "../../../firebase-ios-sdk" */ = {
+ isa = XCLocalSwiftPackageReference;
+ relativePath = "../../../firebase-ios-sdk";
+ };
+/* End XCLocalSwiftPackageReference section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951A02D28AC75000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "~/dev/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+ 8D7951A62D28ADAE000FD694 /* XCRemoteSwiftPackageReference "geofire-objc" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/geofire-objc";
+ requirement = {
+ branch = master;
+ kind = branch;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D15627D2EA0474400D3B017 /* FirebaseAuth */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = FirebaseAuth;
+ };
+ 8D15627F2EA0474400D3B017 /* FirebaseFirestore */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = FirebaseFirestore;
+ };
+ 8D7951A22D28AC82000FD694 /* FirebaseAuth */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A02D28AC75000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAuth;
+ };
+ 8D7951A42D28AC82000FD694 /* FirebaseFirestore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A02D28AC75000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFirestore;
+ };
+ 8D7951A72D28ADBE000FD694 /* GeoFireUtils */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A62D28ADAE000FD694 /* XCRemoteSwiftPackageReference "geofire-objc" */;
+ productName = GeoFireUtils;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 3EABFB171E254C8E00F4BBED /* Project object */;
}
diff --git a/firestore/swift/firestore-smoketest.xcodeproj/xcshareddata/xcschemes/firestore-smoketest.xcscheme b/firestore/swift/firestore-smoketest.xcodeproj/xcshareddata/xcschemes/firestore-smoketest.xcscheme
new file mode 100644
index 00000000..8affb89d
--- /dev/null
+++ b/firestore/swift/firestore-smoketest.xcodeproj/xcshareddata/xcschemes/firestore-smoketest.xcscheme
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/firestore/swift/firestore-smoketest/AppDelegate.swift b/firestore/swift/firestore-smoketest/AppDelegate.swift
index 1fac4ba5..f2f5723d 100644
--- a/firestore/swift/firestore-smoketest/AppDelegate.swift
+++ b/firestore/swift/firestore-smoketest/AppDelegate.swift
@@ -19,13 +19,13 @@ import UIKit
import FirebaseCore
import FirebaseFirestore
-@UIApplicationMain
+@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// [START default_firestore]
FirebaseApp.configure()
diff --git a/firestore/swift/firestore-smoketest/PipelineSnippets.swift b/firestore/swift/firestore-smoketest/PipelineSnippets.swift
new file mode 100644
index 00000000..0c4aa486
--- /dev/null
+++ b/firestore/swift/firestore-smoketest/PipelineSnippets.swift
@@ -0,0 +1,1380 @@
+//
+// Copyright (c) 2025 Google LLC.
+//
+// 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 FirebaseFirestore
+import CoreLocation
+
+public class PipelineSnippets {
+
+ lazy var db = {
+ Firestore.firestore(database: "enterprise")
+ }()
+
+ public func runAllSnippets() {
+ pipelineConcepts()
+ }
+
+ func stagesExpressionsExample() async throws {
+ // [START stages_expressions_example]
+ guard let cutoffDate = Calendar.current.date(byAdding: .month, value: -1, to: Date()) else {
+ return
+ }
+ let snapshot = try await db.pipeline()
+ .collection("productViews")
+ .where(Field("viewedAt").greaterThan(cutoffDate.timeIntervalSince1970))
+ .aggregate([Field("productId").countDistinct().as("uniqueProductViews")])
+ .execute()
+ // [END stages_expressions_example]
+ print(snapshot)
+ }
+
+ func basicRead() async {
+ // [START basic_read]
+ do {
+ // Initialize a Firestore Pipeline instance and specify the "users" collection as the
+ // input stage.
+ let snapshot = try await db.pipeline()
+ .collection("users")
+ .execute() // Execute the pipeline to retrieve documents.
+
+ // Iterate through the documents in the pipeline results, similar to a regular query
+ // snapshot.
+ for result in snapshot.results {
+ print("\(result.id ?? "no ID") => \(result.data)")
+ }
+ } catch {
+ print("Error getting documents with pipeline: \(error)")
+ }
+ // [END basic_read]
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#concepts
+ func pipelineConcepts() {
+ // [START pipeline_concepts]
+ let pipeline = db.pipeline()
+ // Step 1: Start a query with collection scope
+ .collection("cities")
+ // Step 2: Filter the collection
+ .where(Field("population").greaterThan(100000))
+ // Step 3: Sort the remaining documents
+ .sort([Field("name").ascending()])
+ // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have
+ // unintentional results.
+ .limit(10)
+ // [END pipeline_concepts]
+ print(pipeline)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#initialization
+ func pipelineInitialization() {
+ // [START pipeline_initialization]
+ let firestore = Firestore.firestore(database: "enterprise")
+ let pipeline = firestore.pipeline()
+ // [END pipeline_initialization]
+ print(pipeline)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#field_vs_constant_references/
+ func fieldVsConstants() {
+ // [START field_or_constant]
+ let pipeline = db.pipeline()
+ .collection("cities")
+ .where(Field("name").equal(Constant("Toronto")))
+ // [END field_or_constant]
+ print(pipeline)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#input_stages
+ func inputStages() async throws {
+ // [START input_stages]
+ var results: Pipeline.Snapshot
+
+ // Return all restaurants in San Francisco
+ results = try await db.pipeline().collection("cities/sf/restaurants").execute()
+
+ // Return all restaurants
+ results = try await db.pipeline().collectionGroup("restaurants").execute()
+
+ // Return all documents across all collections in the database (the entire database)
+ results = try await db.pipeline().database().execute()
+
+ // Batch read of 3 documents
+ results = try await db.pipeline().documents([
+ db.collection("cities").document("SF"),
+ db.collection("cities").document("DC"),
+ db.collection("cities").document("NY")
+ ]).execute()
+ // [END input_stages]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#where
+ func wherePipeline() async throws {
+ // [START pipeline_where]
+ var results: Pipeline.Snapshot
+
+ results = try await db.pipeline().collection("books")
+ .where(Field("rating").equal(5))
+ .where(Field("published").lessThan(1900))
+ .execute()
+
+ results = try await db.pipeline().collection("books")
+ .where(Field("rating").equal(5) && Field("published").lessThan(1900))
+ .execute()
+ // [END pipeline_where]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#aggregate_distinct
+ func aggregateGroups() async throws {
+ // [START aggregate_groups]
+ let results = try await db.pipeline()
+ .collection("books")
+ .aggregate([
+ Field("rating").average().as("avg_rating")
+ ], groups: [
+ Field("genre")
+ ])
+ .execute()
+ // [END aggregate_groups]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#aggregate_distinct
+ func aggregateDistinct() async throws {
+ // [START aggregate_distinct]
+ let results = try await db.pipeline()
+ .collection("books")
+ .distinct([
+ Field("author").toUpper().as("author"),
+ Field("genre")
+ ])
+ .execute()
+ // [END aggregate_distinct]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#sort
+ func sort() async throws {
+ // [START sort]
+ let results = try await db.pipeline()
+ .collection("books")
+ .sort([
+ Field("release_date").descending(), Field("author").ascending()
+ ])
+ .execute()
+ // [END sort]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#sort
+ func sortComparison() {
+ // [START sort_comparison]
+ let query = db.collection("cities")
+ .order(by: "state")
+ .order(by: "population", descending: true)
+
+ let pipeline = db.pipeline()
+ .collection("books")
+ .sort([
+ Field("release_date").descending(), Field("author").ascending()
+ ])
+ // [END sort_comparison]
+ print(query)
+ print(pipeline)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#functions
+ func functions() async throws {
+ // [START functions_example]
+ var results: Pipeline.Snapshot
+
+ // Type 1: Scalar (for use in non-aggregation stages)
+ // Example: Return the min store price for each book.
+ results = try await db.pipeline().collection("books")
+ .select([
+ Field("current").logicalMinimum(["updated"]).as("price_min")
+ ])
+ .execute()
+
+ // Type 2: Aggregation (for use in aggregate stages)
+ // Example: Return the min price of all books.
+ results = try await db.pipeline().collection("books")
+ .aggregate([Field("price").minimum().as("min_price")])
+ .execute()
+ // [END functions_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#creating_indexes
+ func creatingIndexes() async throws {
+ // [START query_example]
+ let results = try await db.pipeline()
+ .collection("books")
+ .where(Field("published").lessThan(1900))
+ .where(Field("genre").equal("Science Fiction"))
+ .where(Field("rating").greaterThan(4.3))
+ .sort([Field("published").descending()])
+ .execute()
+ // [END query_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#existing_sparse_indexes
+ func sparseIndexes() async throws {
+ // [START sparse_index_example]
+ let results = try await db.pipeline()
+ .collection("books")
+ .where(Field("category").like("%fantasy%"))
+ .execute()
+ // [END sparse_index_example]
+ print(results)
+ }
+
+ func sparseIndexes2() async throws {
+ // [START sparse_index_example_2]
+ let results = try await db.pipeline()
+ .collection("books")
+ .sort([Field("release_date").ascending()])
+ .execute()
+ // [END sparse_index_example_2]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#covered_queries_secondary_indexes
+ func coveredQuery() async throws {
+ // [START covered_query]
+ let results = try await db.pipeline()
+ .collection("books")
+ .where(Field("category").like("%fantasy%"))
+ .where(Field("title").exists())
+ .where(Field("author").exists())
+ .select([Field("title"), Field("author")])
+ .execute()
+ // [END covered_query]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/overview#pagination
+ func pagination() async throws {
+ // [START pagination_not_supported_preview]
+ // Existing pagination via `start(at:)`
+ let query = db.collection("cities").order(by: "population").start(at: [1000000])
+
+ // Private preview workaround using pipelines
+ let pipeline = db.pipeline()
+ .collection("cities")
+ .where(Field("population").greaterThanOrEqual(1000000))
+ .sort([Field("population").descending()])
+ // [END pagination_not_supported_preview]
+ print(query)
+ print(pipeline)
+ }
+
+ // http://cloud.google.com/firestore/docs/pipeline/stages/input/collection#example
+ func collectionStage() async throws {
+ // [START collection_example]
+ let results = try await db.pipeline()
+ .collection("users/bob/games")
+ .sort([Field("name").ascending()])
+ .execute()
+ // [END collection_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/input/collection_group
+ func collectionGroupStage() async throws {
+ // [START collection_group_example]
+ let results = try await db.pipeline()
+ .collectionGroup("games")
+ .sort([Field("name").ascending()])
+ .execute()
+ // [END collection_group_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/input/database
+ func databaseStage() async throws {
+ // [START database_example]
+ // Count all documents in the database
+ let results = try await db.pipeline()
+ .database()
+ .aggregate([CountAll().as("total")])
+ .execute()
+ // [END database_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/input/documents
+ func documentsStage() async throws {
+ // [START documents_example]
+ let results = try await db.pipeline()
+ .documents([
+ db.collection("cities").document("SF"),
+ db.collection("cities").document("DC"),
+ db.collection("cities").document("NY")
+ ]).execute()
+ // [END documents_example]
+ print(results)
+ }
+
+ func replaceWithStage() async throws {
+ // [START initial_data]
+ try await db.collection("cities").document("SF").setData([
+ "name": "San Francisco",
+ "population": 800000,
+ "location": [
+ "country": "USA",
+ "state": "California"
+ ]
+ ])
+ try await db.collection("cities").document("TO").setData([
+ "name": "Toronto",
+ "population": 3000000,
+ "province": "ON",
+ "location": [
+ "country": "Canada",
+ "province": "Ontario"
+ ]
+ ])
+ try await db.collection("cities").document("NY").setData([
+ "name": "New York",
+ "location": [
+ "country": "USA",
+ "state": "New York"
+ ]
+ ])
+ try await db.collection("cities").document("AT").setData([
+ "name": "Atlantis",
+ ])
+ // [END initial_data]
+
+ // [START full_replace]
+ let names = try await db.pipeline()
+ .collection("cities")
+ .replace(with: Field("location"))
+ .execute()
+ // [END full_replace]
+
+ // [START map_merge_overwrite]
+ // unsupported in client SDKs for now
+ // [END map_merge_overwrite]
+ print(names)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/transformation/sample#examples
+ func sampleStage() async throws {
+ // [START sample_example]
+ var results: Pipeline.Snapshot
+
+ // Get a sample of 100 documents in a database
+ results = try await db.pipeline()
+ .database()
+ .sample(count: 100)
+ .execute()
+
+ // Randomly shuffle a list of 3 documents
+ results = try await db.pipeline()
+ .documents([
+ db.collection("cities").document("SF"),
+ db.collection("cities").document("NY"),
+ db.collection("cities").document("DC"),
+ ])
+ .sample(count: 3)
+ .execute()
+ // [END sample_example]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/transformation/sample#examples_2
+ func samplePercent() async throws {
+ // [START sample_percent]
+ // Get a sample of on average 50% of the documents in the database
+ let results = try await db.pipeline()
+ .database()
+ .sample(percentage: 0.5)
+ .execute()
+ // [END sample_percent]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/transformation/union#examples
+ func unionStage() async throws {
+ // [START union_stage]
+ let results = try await db.pipeline()
+ .collection("cities/SF/restaurants")
+ .where(Field("type").equal("Chinese"))
+ .union(with: db.pipeline()
+ .collection("cities/NY/restaurants")
+ .where(Field("type").equal("Italian")))
+ .where(Field("rating").greaterThanOrEqual(4.5))
+ .sort([Field("__name__").descending()])
+ .execute()
+ // [END union_stage]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/transformation/unnest#examples
+ func unnestStage() async throws {
+ // [START unnest_stage]
+ let results = try await db.pipeline()
+ .database()
+ .unnest(Field("arrayField").as("unnestedArrayField"), indexField: "index")
+ .execute()
+ // [END unnest_stage]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/stages/transformation/unnest#examples
+ func unnestStageEmptyOrNonArray() async throws {
+ // [START unnest_edge_cases]
+ // Input
+ // { identifier : 1, neighbors: [ "Alice", "Cathy" ] }
+ // { identifier : 2, neighbors: [] }
+ // { identifier : 3, neighbors: "Bob" }
+
+ let results = try await db.pipeline()
+ .database()
+ .unnest(Field("neighbors").as("unnestedNeighbors"), indexField: "index")
+ .execute()
+
+ // Output
+ // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Alice", index: 0 }
+ // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Cathy", index: 1 }
+ // { identifier: 3, neighbors: "Bob", index: null}
+ // [END unnest_edge_cases]
+ print(results)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#count
+ func countFunction() async throws {
+ // [START count_function]
+ // Total number of books in the collection
+ let countAll = try await db.pipeline()
+ .collection("books")
+ .aggregate([CountAll().as("count")])
+ .execute()
+
+ // Number of books with nonnull `ratings` field
+ let countField = try await db.pipeline()
+ .collection("books")
+ .aggregate([Field("ratings").count().as("count")])
+ .execute()
+ // [END count_function]
+ print(countAll)
+ print(countField)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#count_if
+ func countIfFunction() async throws {
+ // [START count_if]
+ let result = try await db.pipeline()
+ .collection("books")
+ .aggregate([
+ AggregateFunction("count_if", [Field("rating").greaterThan(4)]).as("filteredCount")
+ ])
+ .execute()
+ // [END count_if]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#count_distinct
+ func countDistinctFunction() async throws {
+ // [START count_distinct]
+ let result = try await db.pipeline()
+ .collection("books")
+ .aggregate([AggregateFunction("count_distinct", [Field("author")]).as("unique_authors")])
+ .execute()
+ // [END count_distinct]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#sum
+ func sumFunction() async throws {
+ // [START sum_function]
+ let result = try await db.pipeline()
+ .collection("cities")
+ .aggregate([Field("population").sum().as("totalPopulation")])
+ .execute()
+ // [END sum_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#avg
+ func avgFunction() async throws {
+ // [START avg_function]
+ let result = try await db.pipeline()
+ .collection("cities")
+ .aggregate([Field("population").average().as("averagePopulation")])
+ .execute()
+ // [END avg_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#min
+ func minFunction() async throws {
+ // [START min_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .aggregate([Field("price").minimum().as("minimumPrice")])
+ .execute()
+ // [END min_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/aggregate_functions#max
+ func maxFunction() async throws {
+ // [START max_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .aggregate([Field("price").maximum().as("maximumPrice")])
+ .execute()
+ // [END max_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#add
+ func addFunction() async throws {
+ // [START add_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("soldBooks").add(Field("unsoldBooks")).as("totalBooks")])
+ .execute()
+ // [END add_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#subtract
+ func subtractFunction() async throws {
+ // [START subtract_function]
+ let storeCredit = 7
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("price").subtract(Constant(storeCredit)).as("totalCost")])
+ .execute()
+ // [END subtract_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#multiply
+ func multiplyFunction() async throws {
+ // [START multiply_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("price").multiply(Field("soldBooks")).as("revenue")])
+ .execute()
+ // [END multiply_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#divide
+ func divideFunction() async throws {
+ // [START divide_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("ratings").divide(Field("soldBooks")).as("reviewRate")])
+ .execute()
+ // [END divide_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#mod
+ func modFunction() async throws {
+ // [START mod_function]
+ let displayCapacity = 1000
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("unsoldBooks").mod(Constant(displayCapacity)).as("warehousedBooks")])
+ .execute()
+ // [END mod_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#ceil
+ func ceilFunction() async throws {
+ // [START ceil_function]
+ let booksPerShelf = 100
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("unsoldBooks").divide(Constant(booksPerShelf)).ceil().as("requiredShelves")
+ ])
+ .execute()
+ // [END ceil_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#floor
+ func floorFunction() async throws {
+ // [START floor_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .addFields([
+ Field("wordCount").divide(Field("pages")).floor().as("wordsPerPage")
+ ])
+ .execute()
+ // [END floor_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#round
+ func roundFunction() async throws {
+ // [START round_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("soldBooks").multiply(Field("price")).round().as("partialRevenue")])
+ .aggregate([Field("partialRevenue").sum().as("totalRevenue")])
+ .execute()
+ // [END round_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#pow
+ func powFunction() async throws {
+ // [START pow_function]
+ let googleplex = CLLocation(latitude: 37.4221, longitude: 122.0853)
+ let result = try await db.pipeline()
+ .collection("cities")
+ .addFields([
+ Field("lat").subtract(Constant(googleplex.coordinate.latitude))
+ .multiply(111 /* km per degree */)
+ .pow(2)
+ .as("latitudeDifference"),
+ Field("lng").subtract(Constant(googleplex.coordinate.latitude))
+ .multiply(111 /* km per degree */)
+ .pow(2)
+ .as("longitudeDifference")
+ ])
+ .select([
+ Field("latitudeDifference").add(Field("longitudeDifference")).sqrt()
+ // Inaccurate for large distances or close to poles
+ .as("approximateDistanceToGoogle")
+ ])
+ .execute()
+ // [END pow_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#sqrt
+ func sqrtFunction() async throws {
+ // [START sqrt_function]
+ let googleplex = CLLocation(latitude: 37.4221, longitude: 122.0853)
+ let result = try await db.pipeline()
+ .collection("cities")
+ .addFields([
+ Field("lat").subtract(Constant(googleplex.coordinate.latitude))
+ .multiply(111 /* km per degree */)
+ .pow(2)
+ .as("latitudeDifference"),
+ Field("lng").subtract(Constant(googleplex.coordinate.latitude))
+ .multiply(111 /* km per degree */)
+ .pow(2)
+ .as("longitudeDifference")
+ ])
+ .select([
+ Field("latitudeDifference").add(Field("longitudeDifference")).sqrt()
+ // Inaccurate for large distances or close to poles
+ .as("approximateDistanceToGoogle")
+ ])
+ .execute()
+ // [END sqrt_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#exp
+ func expFunction() async throws {
+ // [START exp_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").exp().as("expRating")])
+ .execute()
+ // [END exp_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#ln
+ func lnFunction() async throws {
+ // [START ln_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").ln().as("lnRating")])
+ .execute()
+ // [END ln_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/arithmetic_functions#log
+ func logFunction() async throws {
+ // [START log_function]
+ // Not supported on iOS
+ // END log_function]
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_concat
+ func arrayConcat() async throws {
+ // [START array_concat]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("genre").arrayConcat([Field("subGenre")]).as("allGenres")])
+ .execute()
+ // [END array_concat]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_contains
+ func arrayContains() async throws {
+ // [START array_contains]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("genre").arrayContains(Constant("mystery")).as("isMystery")])
+ .execute()
+ // [END array_contains]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_contains_all
+ func arrayContainsAll() async throws {
+ // [START array_contains_all]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("genre")
+ .arrayContainsAll([Constant("fantasy"), Constant("adventure")])
+ .as("isFantasyAdventure")
+ ])
+ .execute()
+ // [END array_contains_all]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_contains_any
+ func arrayContainsAny() async throws {
+ // [START array_contains_any]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("genre")
+ .arrayContainsAny([Constant("fantasy"), Constant("nonfiction")])
+ .as("isMysteryOrFantasy")
+ ])
+ .execute()
+ // [END array_contains_any]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_length
+ func arrayLength() async throws {
+ // [START array_length]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("genre").arrayLength().as("genreCount")])
+ .execute()
+ // [END array_length]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/array_functions#array_reverse
+ func arrayReverse() async throws {
+ // [START array_reverse]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("genre").arrayReverse().as("reversedGenres")])
+ .execute()
+ // [END array_reverse]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#eq
+ func equalFunction() async throws {
+ // [START equal_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").equal(5).as("hasPerfectRating")])
+ .execute()
+ // [END equal_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#gt
+ func greaterThanFunction() async throws {
+ // [START greater_than]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").greaterThan(4).as("hasHighRating")])
+ .execute()
+ // [END greater_than]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#gte
+ func greaterThanOrEqualToFunction() async throws {
+ // [START greater_or_equal]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("published").greaterThanOrEqual(1900).as("publishedIn20thCentury")])
+ .execute()
+ // [END greater_or_equal]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#lt
+ func lessThanFunction() async throws {
+ // [START less_than]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("published").lessThan(1923).as("isPublicDomainProbably")])
+ .execute()
+ // [END less_than]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#lte
+ func lessThanOrEqualToFunction() async throws {
+ // [START less_or_equal]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").lessThanOrEqual(2).as("hasBadRating")])
+ .execute()
+ // [END less_or_equal]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/comparison_functions#neq
+ func notEqualFunction() async throws {
+ // [START not_equal]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("title").notEqual("1984").as("not1984")])
+ .execute()
+ // [END not_equal]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/debugging_functions#exists
+ func existsFunction() async throws {
+ // [START exists_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([Field("rating").exists().as("hasRating")])
+ .execute()
+ // [END exists_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#and
+ func andFunction() async throws {
+ // [START and_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ (Field("rating").greaterThan(4) && Field("price").lessThan(10))
+ .as("under10Recommendation")
+ ])
+ .execute()
+ // [END and_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#or
+ func orFunction() async throws {
+ // [START or_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ (Field("genre").equal("Fantasy") || Field("tags").arrayContains("adventure"))
+ .as("matchesSearchFilters")
+ ])
+ .execute()
+ // [END or_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#xor
+ func xorFunction() async throws {
+ // [START xor_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ (Field("tags").arrayContains("magic") ^ Field("tags").arrayContains("nonfiction"))
+ .as("matchesSearchFilters")
+ ])
+ .execute()
+ // [END xor_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#not
+ func notFunction() async throws {
+ // [START not_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ (!Field("tags").arrayContains("nonfiction"))
+ .as("isFiction")
+ ])
+ .execute()
+ // [END not_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#cond
+ func condFunction() async throws {
+ // [START cond_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("tags").arrayConcat([
+ ConditionalExpression(
+ Field("pages").greaterThan(100),
+ then: Constant("longRead"),
+ else: Constant("shortRead")
+ )
+ ]).as("extendedTags")
+ ])
+ .execute()
+ // [END cond_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#eq_any
+ func equalAnyFunction() async throws {
+ // [START eq_any]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("genre").equalAny(["Science Fiction", "Psychological Thriller"])
+ .as("matchesGenreFilters")
+ ])
+ .execute()
+ // [END eq_any]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#not_eq_any
+ func notEqualAnyFunction() async throws {
+ // [START not_eq_any]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("author").notEqualAny(["George Orwell", "F. Scott Fitzgerald"])
+ .as("byExcludedAuthors")
+ ])
+ .execute()
+ // [END not_eq_any]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#max
+ func maxLogicalFunction() async throws {
+ // [START max_logical_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("rating").logicalMaximum([1]).as("flooredRating")
+ ])
+ .execute()
+ // [END max_logical_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/logical_functions#min
+ func minLogicalFunction() async throws {
+ // [START min_logical_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("rating").logicalMinimum([5]).as("cappedRating")
+ ])
+ .execute()
+ // [END min_logical_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/map_functions#map_get
+ func mapGetFunction() async throws {
+ // [START map_get]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("awards").mapGet("pulitzer").as("hasPulitzerAward")
+ ])
+ .execute()
+ // [END map_get]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#byte_length
+ func byteLengthFunction() async throws {
+ // [START byte_length]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("title").byteLength().as("titleByteLength")
+ ])
+ .execute()
+ // [END byte_length]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#char_length
+ func charLengthFunction() async throws {
+ // [START char_length]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("title").charLength().as("titleCharLength")
+ ])
+ .execute()
+ // [END char_length]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#starts_with
+ func startsWithFunction() async throws {
+ // [START starts_with]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("title").startsWith("The")
+ .as("needsSpecialAlphabeticalSort")
+ ])
+ .execute()
+ // [END starts_with]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#ends_with
+ func endsWithFunction() async throws {
+ // [START ends_with]
+ let result = try await db.pipeline()
+ .collection("inventory/devices/laptops")
+ .select([
+ Field("name").endsWith("16 inch")
+ .as("16InLaptops")
+ ])
+ .execute()
+ // [END ends_with]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#like
+ func likeFunction() async throws {
+ // [START like]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("genre").like("%Fiction")
+ .as("anyFiction")
+ ])
+ .execute()
+ // [END like]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#regex_contains
+ func regexContainsFunction() async throws {
+ // [START regex_contains]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("title").regexContains("Firestore (Enterprise|Standard)")
+ .as("isFirestoreRelated")
+ ])
+ .execute()
+ // [END regex_contains]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#regex_match
+ func regexMatchFunction() async throws {
+ // [START regex_match]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("title").regexMatch("Firestore (Enterprise|Standard)")
+ .as("isFirestoreExactly")
+ ])
+ .execute()
+ // [END regex_match]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_concat
+ func strConcatFunction() async throws {
+ // [START str_concat]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("title").concat([" by ", Field("author")])
+ .as("fullyQualifiedTitle")
+ ])
+ .execute()
+ // [END str_concat]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_contains
+ func strContainsFunction() async throws {
+ // [START string_contains]
+ let result = try await db.pipeline()
+ .collection("articles")
+ .select([
+ Field("body").stringContains("Firestore")
+ .as("isFirestoreRelated")
+ ])
+ .execute()
+ // [END string_contains]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#to_upper
+ func toUpperFunction() async throws {
+ // [START to_upper]
+ let result = try await db.pipeline()
+ .collection("authors")
+ .select([
+ Field("name").toUpper()
+ .as("uppercaseName")
+ ])
+ .execute()
+ // [END to_upper]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#to_lower
+ func toLowerFunction() async throws {
+ // [START to_lower]
+ let result = try await db.pipeline()
+ .collection("authors")
+ .select([
+ Field("genre").toLower().equal("fantasy")
+ .as("isFantasy")
+ ])
+ .execute()
+ // [END to_lower]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#substr
+ func substrFunction() async throws {
+ // [START substr_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .where(Field("title").startsWith("The "))
+ .select([
+ Field("title").substring(position: 4)
+ .as("titleWithoutLeadingThe")
+ ])
+ .execute()
+ // [END substr_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_reverse
+ func strReverseFunction() async throws {
+ // [START str_reverse]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("name").reverse().as("reversedName")
+ ])
+ .execute()
+ // [END str_reverse]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_trim
+ func strTrimFunction() async throws {
+ // [START trim_function]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("name").trim(" \n\t").as("whitespaceTrimmedName")
+ ])
+ .execute()
+ // [END trim_function]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_replace
+ func strReplaceFunction() async throws {
+ // not yet supported until GA
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/string_functions#str_split
+ func strSplitFunction() async throws {
+ // not yet supported until GA
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#unix_micros_to_timestamp
+ func unixMicrosToTimestampFunction() async throws {
+ // [START unix_micros_timestamp]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("createdAtMicros").unixMicrosToTimestamp().as("createdAtString")
+ ])
+ .execute()
+ // [END unix_micros_timestamp]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#unix_millis_to_timestamp
+ func unixMillisToTimestampFunction() async throws {
+ // [START unix_millis_timestamp]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("createdAtMillis").unixMillisToTimestamp().as("createdAtString")
+ ])
+ .execute()
+ // [END unix_millis_timestamp]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#unix_seconds_to_timestamp
+ func unixSecondsToTimestampFunction() async throws {
+ // [START unix_seconds_timestamp]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("createdAtSeconds").unixSecondsToTimestamp().as("createdAtString")
+ ])
+ .execute()
+ // [END unix_seconds_timestamp]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#timestamp_add
+ func timestampAddFunction() async throws {
+ // [START timestamp_add]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("createdAt").timestampAdd(3653, .day).as("expiresAt")
+ ])
+ .execute()
+ // [END timestamp_add]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#timestamp_sub
+ func timestampSubFunction() async throws {
+ // [START timestamp_sub]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("expiresAt").timestampSubtract(14, .day).as("sendWarningTimestamp")
+ ])
+ .execute()
+ // [END timestamp_sub]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#timestamp_to_unix_micros
+ func timestampToUnixMicrosFunction() async throws {
+ // [START timestamp_unix_micros]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("dateString").timestampToUnixMicros().as("unixMicros")
+ ])
+ .execute()
+ // [END timestamp_unix_micros]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#timestamp_to_unix_millis
+ func timestampToUnixMillisFunction() async throws {
+ // [START timestamp_unix_millis]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("dateString").timestampToUnixMillis().as("unixMillis")
+ ])
+ .execute()
+ // [END timestamp_unix_millis]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/timestamp_functions#timestamp_to_unix_seconds
+ func timestampToUnixSecondsFunction() async throws {
+ // [START timestamp_unix_seconds]
+ let result = try await db.pipeline()
+ .collection("documents")
+ .select([
+ Field("dateString").timestampToUnixSeconds().as("unixSeconds")
+ ])
+ .execute()
+ // [END timestamp_unix_seconds]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/vector_functions#cosine_distance
+ func cosineDistanceFunction() async throws {
+ // [START cosine_distance]
+ let sampleVector = [0.0, 1, 2, 3, 4, 5]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("embedding").cosineDistance(sampleVector).as("cosineDistance")
+ ])
+ .execute()
+ // [END cosine_distance]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/vector_functions#dot_product
+ func dotProductFunction() async throws {
+ // [START dot_product]
+ let sampleVector = [0.0, 1, 2, 3, 4, 5]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("embedding").dotProduct(sampleVector).as("dotProduct")
+ ])
+ .execute()
+ // [END dot_product]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/vector_functions#euclidean_distance
+ func euclideanDistanceFunction() async throws {
+ // [START euclidean_distance]
+ let sampleVector = [0.0, 1, 2, 3, 4, 5]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("embedding").euclideanDistance(sampleVector).as("euclideanDistance")
+ ])
+ .execute()
+ // [END euclidean_distance]
+ print(result)
+ }
+
+ // https://cloud.google.com/firestore/docs/pipeline/functions/vector_functions#vector_length
+ func vectorLengthFunction() async throws {
+ // [START vector_length]
+ let result = try await db.pipeline()
+ .collection("books")
+ .select([
+ Field("embedding").vectorLength().as("vectorLength")
+ ])
+ .execute()
+ // [END vector_length]
+ print(result)
+ }
+}
diff --git a/firestore/swift/firestore-smoketest/SolutionAggregationViewController.swift b/firestore/swift/firestore-smoketest/SolutionAggregationViewController.swift
index c8e02157..743c861f 100644
--- a/firestore/swift/firestore-smoketest/SolutionAggregationViewController.swift
+++ b/firestore/swift/firestore-smoketest/SolutionAggregationViewController.swift
@@ -19,85 +19,79 @@ import UIKit
import FirebaseCore
import FirebaseFirestore
-class SolutionAggregationViewController: UIViewController {
-
- var db: Firestore!
-
- // [START restaurant_struct]
- struct Restaurant {
-
- let name: String
- let avgRating: Float
- let numRatings: Int
-
- init(name: String, avgRating: Float, numRatings: Int) {
- self.name = name
- self.avgRating = avgRating
- self.numRatings = numRatings
- }
-
- }
-
- let arinell = Restaurant(name: "Arinell Pizza", avgRating: 4.65, numRatings: 683)
- // [END restaurant_struct]
-
- struct Rating {
- let rating: Float
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
- db = Firestore.firestore()
+class SolutionAggregationViewController: @unchecked Sendable {
+
+ nonisolated(unsafe) lazy var db: Firestore = {
+ Firestore.firestore()
+ }()
+
+ // [START restaurant_struct]
+ struct Restaurant {
+
+ let name: String
+ let avgRating: Float
+ let numRatings: Int
+
+ }
+
+ let arinell = Restaurant(name: "Arinell Pizza", avgRating: 4.65, numRatings: 683)
+ // [END restaurant_struct]
+
+ struct Rating {
+ let rating: Float
+ }
+
+ func getRatingsSubcollection() async {
+ // [START get_ratings_subcollection]
+ do {
+ let snapshot = try await db.collection("restaurants")
+ .document("arinell-pizza")
+ .collection("ratings")
+ .getDocuments()
+ print(snapshot)
+ } catch {
+ print(error)
}
-
- func getRatingsSubcollection() {
- // [START get_ratings_subcollection]
- db.collection("restaurants")
- .document("arinell-pizza")
- .collection("ratings")
- .getDocuments() { (querySnapshot, err) in
-
- // ...
-
+ // [END get_ratings_subcollection]
+ }
+
+ // [START add_rating_transaction]
+ func addRatingTransaction(restaurantRef: DocumentReference, rating: Float) async {
+ let ratingRef: DocumentReference = restaurantRef.collection("ratings").document()
+
+ do {
+ let _ = try await db.runTransaction({ (transaction, errorPointer) -> Any? in
+ do {
+ let restaurantDocument = try transaction.getDocument(restaurantRef).data()
+ guard var restaurantData = restaurantDocument else { return nil }
+
+ // Compute new number of ratings
+ let numRatings = restaurantData["numRatings"] as! Int
+ let newNumRatings = numRatings + 1
+
+ // Compute new average rating
+ let avgRating = restaurantData["avgRating"] as! Float
+ let oldRatingTotal = avgRating * Float(numRatings)
+ let newAvgRating = (oldRatingTotal + rating) / Float(newNumRatings)
+
+ // Set new restaurant info
+ restaurantData["numRatings"] = newNumRatings
+ restaurantData["avgRating"] = newAvgRating
+
+ // Commit to Firestore
+ transaction.setData(restaurantData, forDocument: restaurantRef)
+ transaction.setData(["rating": rating], forDocument: ratingRef)
+ } catch {
+ // Error getting restaurant data
+ // ...
}
- // [END get_ratings_subcollection]
- }
- // [START add_rating_transaction]
- func addRatingTransaction(restaurantRef: DocumentReference, rating: Float) {
- let ratingRef: DocumentReference = restaurantRef.collection("ratings").document()
-
- db.runTransaction({ (transaction, errorPointer) -> Any? in
- do {
- let restaurantDocument = try transaction.getDocument(restaurantRef).data()
- guard var restaurantData = restaurantDocument else { return nil }
-
- // Compute new number of ratings
- let numRatings = restaurantData["numRatings"] as! Int
- let newNumRatings = numRatings + 1
-
- // Compute new average rating
- let avgRating = restaurantData["avgRating"] as! Float
- let oldRatingTotal = avgRating * Float(numRatings)
- let newAvgRating = (oldRatingTotal + rating) / Float(newNumRatings)
-
- // Set new restaurant info
- restaurantData["numRatings"] = newNumRatings
- restaurantData["avgRating"] = newAvgRating
-
- // Commit to Firestore
- transaction.setData(restaurantData, forDocument: restaurantRef)
- transaction.setData(["rating": rating], forDocument: ratingRef)
- } catch {
- // Error getting restaurant data
- // ...
- }
-
- return nil
- }) { (object, err) in
- // ...
- }
+ return nil
+ })
+ } catch {
+ // ...
}
- // [END add_rating_transaction]
+ }
+ // [END add_rating_transaction]
}
diff --git a/firestore/swift/firestore-smoketest/SolutionArraysViewController.swift b/firestore/swift/firestore-smoketest/SolutionArraysViewController.swift
index 4f51b610..aece8f89 100644
--- a/firestore/swift/firestore-smoketest/SolutionArraysViewController.swift
+++ b/firestore/swift/firestore-smoketest/SolutionArraysViewController.swift
@@ -21,94 +21,86 @@ import FirebaseFirestore
class SolutionArraysViewController: UIViewController {
- var db: Firestore!
-
- override func viewDidLoad() {
- super.viewDidLoad()
- db = Firestore.firestore()
- }
-
- func queryInCategory() {
- // [START query_in_category]
- db.collection("posts")
- .whereField("categories.cats", isEqualTo: true)
- .getDocuments() { (querySnapshot, err) in
-
- // ...
-
- }
- // [END query_in_category]
- }
-
- func queryInCategoryTimestamp() {
- // [START query_in_category_timestamp_invalid]
- db.collection("posts")
- .whereField("categories.cats", isEqualTo: true)
- .order(by: "timestamp")
- // [END query_in_category_timestamp_invalid]
-
- // [START query_in_category_timestamp]
- db.collection("posts")
- .whereField("categories.cats", isGreaterThan: 0)
- .order(by: "categories.cats")
- // [END query_in_category_timestamp]
+ var db: Firestore!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ db = Firestore.firestore()
+ }
+
+ func queryInCategory() async {
+ // [START query_in_category]
+ do {
+ let querySnapshot = try await db.collection("posts")
+ .whereField("categories.cats", isEqualTo: true)
+ .getDocuments()
+ // Do something with the snapshot
+ print(querySnapshot)
+ } catch {
+ print("Error: \(error)")
}
-
- // [START post_with_array]
- struct PostArray {
-
- let title: String
- let categories: [String]
-
- init(title: String, categories: [String]) {
- self.title = title
- self.categories = categories
- }
-
+ // [END query_in_category]
+ }
+
+ func queryInCategoryTimestamp() {
+ // [START query_in_category_timestamp_invalid]
+ db.collection("posts")
+ .whereField("categories.cats", isEqualTo: true)
+ .order(by: "timestamp")
+ // [END query_in_category_timestamp_invalid]
+
+ // [START query_in_category_timestamp]
+ db.collection("posts")
+ .whereField("categories.cats", isGreaterThan: 0)
+ .order(by: "categories.cats")
+ // [END query_in_category_timestamp]
+ }
+
+ // [START post_with_array]
+ struct PostArray {
+
+ let title: String
+ let categories: [String]
+
+ init(title: String, categories: [String]) {
+ self.title = title
+ self.categories = categories
}
- let myArrayPost = PostArray(title: "My great post",
- categories: ["technology", "opinion", "cats"])
- // [END post_with_array]
+ }
- // [START post_with_dict]
- struct PostDict {
+ let myArrayPost = PostArray(title: "My great post",
+ categories: ["technology", "opinion", "cats"])
+ // [END post_with_array]
- let title: String
- let categories: [String: Bool]
+ // [START post_with_dict]
+ struct PostDict {
- init(title: String, categories: [String: Bool]) {
- self.title = title
- self.categories = categories
- }
+ let title: String
+ let categories: [String: Bool]
- }
-
- let post = PostDict(title: "My great post", categories: [
- "technology": true,
- "opinion": true,
- "cats": true
- ])
- // [END post_with_dict]
+ }
- // [START post_with_dict_advanced]
- struct PostDictAdvanced {
+ let post = PostDict(title: "My great post", categories: [
+ "technology": true,
+ "opinion": true,
+ "cats": true
+ ])
+ // [END post_with_dict]
- let title: String
- let categories: [String: UInt64]
+ // [START post_with_dict_advanced]
+ struct PostDictAdvanced {
- init(title: String, categories: [String: UInt64]) {
- self.title = title
- self.categories = categories
- }
+ let title: String
+ let categories: [String: UInt64]
- }
+ }
- let dictPost = PostDictAdvanced(title: "My great post", categories: [
- "technology": 1502144665,
- "opinion": 1502144665,
- "cats": 1502144665
- ])
- // [END post_with_dict_advanced]
+ let dictPost = PostDictAdvanced(title: "My great post", categories: [
+ "technology": 1502144665,
+ "opinion": 1502144665,
+ "cats": 1502144665
+ ])
+ // [END post_with_dict_advanced]
}
diff --git a/firestore/swift/firestore-smoketest/SolutionBundles.swift b/firestore/swift/firestore-smoketest/SolutionBundles.swift
new file mode 100644
index 00000000..39a839a3
--- /dev/null
+++ b/firestore/swift/firestore-smoketest/SolutionBundles.swift
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2021 Google LLC
+//
+// 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 FirebaseFirestore
+
+class SolutionBundles {
+
+ // [START fs_bundle_load]
+ // Utility function for errors when loading bundles.
+ func bundleLoadError(reason: String) -> NSError {
+ return NSError(domain: "FIRSampleErrorDomain",
+ code: 0,
+ userInfo: [NSLocalizedFailureReasonErrorKey: reason])
+ }
+
+ func fetchRemoteBundle(for firestore: Firestore,
+ from url: URL) async throws -> LoadBundleTaskProgress {
+ guard let inputStream = InputStream(url: url) else {
+ let error = self.bundleLoadError(reason: "Unable to create stream from the given url: \(url)")
+ throw error
+ }
+
+ return try await firestore.loadBundle(inputStream)
+ }
+
+ // Fetches a specific named query from the provided bundle.
+ func loadQuery(named queryName: String,
+ fromRemoteBundle bundleURL: URL,
+ with store: Firestore) async throws -> Query {
+ let _ = try await fetchRemoteBundle(for: store, from: bundleURL)
+ if let query = await store.getQuery(named: queryName) {
+ return query
+ } else {
+ throw bundleLoadError(reason: "Could not find query named \(queryName)")
+ }
+ }
+
+ // Load a query and fetch its results from a bundle.
+ func runStoriesQuery() async {
+ let queryName = "latest-stories-query"
+ let firestore = Firestore.firestore()
+ let remoteBundle = URL(string: "https://example.com/createBundle")!
+
+ do {
+ let query = try await loadQuery(named: queryName,
+ fromRemoteBundle: remoteBundle,
+ with: firestore)
+ let snapshot = try await query.getDocuments()
+ print(snapshot)
+ // handle query results
+ } catch {
+ print(error)
+ }
+ }
+ // [END fs_bundle_load]
+
+ // [START fs_simple_bundle_load]
+ func loadBundle(from bundleURL: URL) {
+ let firestore = Firestore.firestore()
+ let data: Data
+ do {
+ try data = Data(contentsOf: bundleURL)
+ } catch {
+ print(error)
+ return
+ }
+ firestore.loadBundle(data)
+ }
+ // [END fs_simple_bundle_load]
+
+ // [START fs_named_query]
+ func runNamedQuery() async {
+ let firestore = Firestore.firestore()
+ let queryName = "coll-query"
+ do {
+ guard let query = await firestore.getQuery(named: queryName) else {
+ throw bundleLoadError(reason: "Could not find query named \(queryName)")
+ }
+ let snapshot = try await query.getDocuments()
+ print(snapshot)
+ // ...
+ } catch {
+ print(error)
+ }
+ }
+ // [END fs_named_query]
+
+ // [START bundle_observe_progress]
+ func observeProgress(of loadBundleTask: LoadBundleTask) {
+ let handle = loadBundleTask.addObserver { progress in
+ print("Loaded \(progress.bytesLoaded) bytes out of \(progress.totalBytes) total")
+ }
+
+ // ...
+ loadBundleTask.removeObserverWith(handle: handle)
+ }
+ // [END bundle_observe_progress]
+
+}
diff --git a/firestore/swift/firestore-smoketest/SolutionCountersViewController.swift b/firestore/swift/firestore-smoketest/SolutionCountersViewController.swift
index 85809860..ab8df095 100644
--- a/firestore/swift/firestore-smoketest/SolutionCountersViewController.swift
+++ b/firestore/swift/firestore-smoketest/SolutionCountersViewController.swift
@@ -21,71 +21,72 @@ import FirebaseFirestore
class SolutionCountersController: UIViewController {
- var db: Firestore!
+ var db: Firestore!
- override func viewDidLoad() {
- super.viewDidLoad()
- db = Firestore.firestore()
- }
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ db = Firestore.firestore()
+ }
- // [START counter_structs]
- // counters/${ID}
- struct Counter {
- let numShards: Int
+ // [START counter_structs]
+ // counters/${ID}
+ struct Counter {
+ let numShards: Int
- init(numShards: Int) {
- self.numShards = numShards
- }
+ init(numShards: Int) {
+ self.numShards = numShards
}
+ }
- // counters/${ID}/shards/${NUM}
- struct Shard {
- let count: Int
+ // counters/${ID}/shards/${NUM}
+ struct Shard {
+ let count: Int
- init(count: Int) {
- self.count = count
- }
+ init(count: Int) {
+ self.count = count
}
- // [END counter_structs]
+ }
+ // [END counter_structs]
- // [START create_counter]
- func createCounter(ref: DocumentReference, numShards: Int) {
- ref.setData(["numShards": numShards]){ (err) in
- for i in 0...numShards {
- ref.collection("shards").document(String(i)).setData(["count": 0])
- }
- }
+ // [START create_counter]
+ func createCounter(ref: DocumentReference, numShards: Int) async {
+ do {
+ try await ref.setData(["numShards": numShards])
+ for i in 0...numShards {
+ try await ref.collection("shards").document(String(i)).setData(["count": 0])
+ }
+ } catch {
+ // ...
}
- // [END create_counter]
+ }
+ // [END create_counter]
- // [START increment_counter]
- func incrementCounter(ref: DocumentReference, numShards: Int) {
- // Select a shard of the counter at random
- let shardId = Int(arc4random_uniform(UInt32(numShards)))
- let shardRef = ref.collection("shards").document(String(shardId))
+ // [START increment_counter]
+ func incrementCounter(ref: DocumentReference, numShards: Int) {
+ // Select a shard of the counter at random
+ let shardId = Int(arc4random_uniform(UInt32(numShards)))
+ let shardRef = ref.collection("shards").document(String(shardId))
- shardRef.updateData([
- "count": FieldValue.increment(Int64(1))
- ])
- }
- // [END increment_counter]
+ shardRef.updateData([
+ "count": FieldValue.increment(Int64(1))
+ ])
+ }
+ // [END increment_counter]
- // [START get_count]
- func getCount(ref: DocumentReference) {
- ref.collection("shards").getDocuments() { (querySnapshot, err) in
- var totalCount = 0
- if err != nil {
- // Error getting shards
- // ...
- } else {
- for document in querySnapshot!.documents {
- let count = document.data()["count"] as! Int
- totalCount += count
- }
- }
+ // [START get_count]
+ func getCount(ref: DocumentReference) async {
+ do {
+ let querySnapshot = try await ref.collection("shards").getDocuments()
+ var totalCount = 0
+ for document in querySnapshot.documents {
+ let count = document.data()["count"] as! Int
+ totalCount += count
+ }
- print("Total count is \(totalCount)")
- }
+ print("Total count is \(totalCount)")
+ } catch {
+ // handle error
}
- // [END get_count]
+ }
+ // [END get_count]
}
diff --git a/firestore/swift/firestore-smoketest/SolutionGeoPointViewController.swift b/firestore/swift/firestore-smoketest/SolutionGeoPointViewController.swift
new file mode 100644
index 00000000..963f3f78
--- /dev/null
+++ b/firestore/swift/firestore-smoketest/SolutionGeoPointViewController.swift
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2019 Google LLC
+//
+// 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 FirebaseCore
+import FirebaseFirestore
+import GeoFireUtils
+import CoreLocation
+
+class SolutionGeoPointController: UIViewController {
+
+ var db: Firestore!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ db = Firestore.firestore()
+ }
+
+ func storeGeoHash() {
+ // [START fs_geo_add_hash]
+ // Compute the GeoHash for a lat/lng point
+ let latitude = 51.5074
+ let longitude = 0.12780
+ let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
+
+ let hash = GFUtils.geoHash(forLocation: location)
+
+ // Add the hash and the lat/lng to the document. We will use the hash
+ // for queries and the lat/lng for distance comparisons.
+ let documentData: [String: Any] = [
+ "geohash": hash,
+ "lat": latitude,
+ "lng": longitude
+ ]
+
+ let londonRef = db.collection("cities").document("LON")
+ londonRef.updateData(documentData) { error in
+ // ...
+ }
+ // [END fs_geo_add_hash]
+ }
+
+ func geoQuery() async {
+ // [START fs_geo_query_hashes]
+ // Find cities within 50km of London
+ let center = CLLocationCoordinate2D(latitude: 51.5074, longitude: 0.1278)
+ let radiusInM: Double = 50 * 1000
+
+ // Each item in 'bounds' represents a startAt/endAt pair. We have to issue
+ // a separate query for each pair. There can be up to 9 pairs of bounds
+ // depending on overlap, but in most cases there are 4.
+ let queryBounds = GFUtils.queryBounds(forLocation: center,
+ withRadius: radiusInM)
+ let queries = queryBounds.map { bound -> Query in
+ return db.collection("cities")
+ .order(by: "geohash")
+ .start(at: [bound.startValue])
+ .end(at: [bound.endValue])
+ }
+
+ @Sendable func fetchMatchingDocs(from query: Query,
+ center: CLLocationCoordinate2D,
+ radiusInMeters: Double) async throws -> [QueryDocumentSnapshot] {
+ let snapshot = try await query.getDocuments()
+ // Collect all the query results together into a single list
+ return snapshot.documents.filter { document in
+ let lat = document.data()["lat"] as? Double ?? 0
+ let lng = document.data()["lng"] as? Double ?? 0
+ let coordinates = CLLocation(latitude: lat, longitude: lng)
+ let centerPoint = CLLocation(latitude: center.latitude, longitude: center.longitude)
+
+ // We have to filter out a few false positives due to GeoHash accuracy, but
+ // most will match
+ let distance = GFUtils.distance(from: centerPoint, to: coordinates)
+ return distance <= radiusInM
+ }
+ }
+
+ // After all callbacks have executed, matchingDocs contains the result. Note that this code
+ // executes all queries serially, which may not be optimal for performance.
+ do {
+ let matchingDocs = try await withThrowingTaskGroup(of: [QueryDocumentSnapshot].self) { group -> [QueryDocumentSnapshot] in
+ for query in queries {
+ group.addTask {
+ try await fetchMatchingDocs(from: query, center: center, radiusInMeters: radiusInM)
+ }
+ }
+ var matchingDocs = [QueryDocumentSnapshot]()
+ for try await documents in group {
+ matchingDocs.append(contentsOf: documents)
+ }
+ return matchingDocs
+ }
+
+ print("Docs matching geoquery: \(matchingDocs)")
+ } catch {
+ print("Unable to fetch snapshot data. \(error)")
+ }
+ // [END fs_geo_query_hashes]
+ }
+}
diff --git a/firestore/swift/firestore-smoketest/ViewController.swift b/firestore/swift/firestore-smoketest/ViewController.swift
index 56405181..1d29b193 100644
--- a/firestore/swift/firestore-smoketest/ViewController.swift
+++ b/firestore/swift/firestore-smoketest/ViewController.swift
@@ -21,1209 +21,1460 @@ import FirebaseFirestore
class ViewController: UIViewController {
- var db: Firestore!
+ var smokeTests: SmokeTests!
- override func viewDidLoad() {
- super.viewDidLoad()
+ override func viewDidLoad() {
+ super.viewDidLoad()
- // [START setup]
- let settings = FirestoreSettings()
+ // [START setup]
+ let settings = FirestoreSettings()
- Firestore.firestore().settings = settings
- // [END setup]
- db = Firestore.firestore()
- }
-
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- }
-
- @IBAction func didTouchSmokeTestButton(_ sender: AnyObject) {
- // Quickstart
- addAdaLovelace()
- addAlanTuring()
- getCollection()
- listenForUsers()
-
- // Structure Data
- demonstrateReferences()
-
- // Save Data
- setDocument()
- dataTypes()
- setData()
- addDocument()
- newDocument()
- updateDocument()
- createIfMissing()
- updateDocumentNested()
- deleteDocument()
- deleteCollection()
- deleteField()
- serverTimestamp()
- serverTimestampOptions()
- simpleTransaction()
- transaction()
- writeBatch()
-
- // Retrieve Data
- exampleData()
- exampleDataCollectionGroup()
- getDocument()
- customClassGetDocument()
- listenDocument()
- listenDocumentLocal()
- listenWithMetadata()
- getMultiple()
- getMultipleAll()
- listenMultiple()
- listenDiffs()
- listenState()
- detachListener()
- handleListenErrors()
-
- // Query Data
- simpleQueries()
- exampleFilters()
- onlyCapitals()
- chainFilters()
- validRangeFilters()
-
- // Can't run this since it throws a fatal error
- // invalidRangeFilters()
-
- orderAndLimit()
- orderAndLimitDesc()
- orderMultiple()
- filterAndOrder()
- validFilterAndOrder()
-
- // Can't run this since it throws a fatal error
- // invalidFilterAndOrder()
-
- // Enable Offline
- // Can't run this since it throws a fatal error
- // enableOffline()
- listenToOffline()
- toggleOffline()
- setupCacheSize()
-
- // Cursors
- simpleCursor()
- snapshotCursor()
- paginate()
- multiCursor()
- }
-
- @IBAction func didTouchDeleteButton(_ sender: AnyObject) {
- deleteCollection(collection: "users")
- deleteCollection(collection: "cities")
- }
+ Firestore.firestore().settings = settings
+ // [END setup]
+ smokeTests = SmokeTests(Firestore.firestore())
+ }
- private func deleteCollection(collection: String) {
- db.collection(collection).getDocuments() { (querySnapshot, err) in
- if let err = err {
- print("Error getting documents: \(err)")
- return
- }
-
- for document in querySnapshot!.documents {
- print("Deleting \(document.documentID) => \(document.data())")
- document.reference.delete()
- }
- }
- }
+ @IBAction func didTouchSmokeTestButton(_ sender: AnyObject) {
+ smokeTests.runAllSmokeTests()
+ }
- private func setupCacheSize() {
- // [START fs_setup_cache]
- let settings = Firestore.firestore().settings
- settings.cacheSizeBytes = FirestoreCacheSizeUnlimited
- Firestore.firestore().settings = settings
- // [END fs_setup_cache]
- }
+ @IBAction func didTouchDeleteButton(_ sender: AnyObject) {
+ smokeTests.deleteCollection(collection: "users")
+ smokeTests.deleteCollection(collection: "cities")
+ }
- // =======================================================================================
- // ======== https://firebase.google.com/preview/firestore/client/quickstart ==============
- // =======================================================================================
-
- private func addAdaLovelace() {
- // [START add_ada_lovelace]
- // Add a new document with a generated ID
- var ref: DocumentReference? = nil
- ref = db.collection("users").addDocument(data: [
- "first": "Ada",
- "last": "Lovelace",
- "born": 1815
- ]) { err in
- if let err = err {
- print("Error adding document: \(err)")
- } else {
- print("Document added with ID: \(ref!.documentID)")
- }
- }
- // [END add_ada_lovelace]
- }
-
- private func addAlanTuring() {
- var ref: DocumentReference? = nil
-
- // [START add_alan_turing]
- // Add a second document with a generated ID.
- ref = db.collection("users").addDocument(data: [
- "first": "Alan",
- "middle": "Mathison",
- "last": "Turing",
- "born": 1912
- ]) { err in
- if let err = err {
- print("Error adding document: \(err)")
- } else {
- print("Document added with ID: \(ref!.documentID)")
- }
- }
- // [END add_alan_turing]
- }
-
- private func getCollection() {
- // [START get_collection]
- db.collection("users").getDocuments() { (querySnapshot, err) in
- if let err = err {
- print("Error getting documents: \(err)")
- } else {
- for document in querySnapshot!.documents {
- print("\(document.documentID) => \(document.data())")
- }
- }
- }
- // [END get_collection]
- }
+}
- private func listenForUsers() {
- // [START listen_for_users]
- // Listen to a query on a collection.
- //
- // We will get a first snapshot with the initial results and a new
- // snapshot each time there is a change in the results.
- db.collection("users")
- .whereField("born", isLessThan: 1900)
- .addSnapshotListener { querySnapshot, error in
- guard let snapshot = querySnapshot else {
- print("Error retreiving snapshots \(error!)")
- return
- }
- print("Current users born before 1900: \(snapshot.documents.map { $0.data() })")
- }
- // [END listen_for_users]
- }
+class SmokeTests: @unchecked Sendable {
+
+ nonisolated(unsafe) private let db: Firestore
+
+ init(_ db: Firestore) {
+ self.db = db
+ }
+
+ func runAllSmokeTests() {
+ // Quickstart
+ Task {
+ await addAdaLovelace()
+ await addAlanTuring()
+ await getCollection()
+ listenForUsers()
+ }
+
+ // Structure Data
+ demonstrateReferences()
+
+ // Save Data
+ Task {
+ await setDocument()
+ await dataTypes()
+ setData()
+ await addDocument()
+ newDocument()
+ await updateDocument()
+ createIfMissing()
+ await updateDocumentNested()
+ await deleteDocument()
+ deleteCollection()
+ await deleteField()
+ await serverTimestamp()
+ serverTimestampOptions()
+ await simpleTransaction()
+ await transaction()
+ await writeBatch()
+ }
+
+ // Retrieve Data
+ Task {
+ exampleData()
+ exampleDataCollectionGroup()
+ await getDocument()
+ await customClassGetDocument()
+ listenDocument()
+ listenDocumentLocal()
+ listenWithMetadata()
+ await getMultiple()
+ await getMultipleAll()
+ listenMultiple()
+ listenDiffs()
+ listenState()
+ detachListener()
+ handleListenErrors()
+ }
+
+ // Query Data
+ simpleQueries()
+ exampleFilters()
+ onlyCapitals()
+ chainFilters()
+ validRangeFilters()
+
+ // IN Queries
+ arrayContainsAnyQueries()
+ inQueries()
+
+ // Can't run this since it throws a fatal error
+ // invalidRangeFilters()
+
+ orderAndLimit()
+ orderAndLimitDesc()
+ orderMultiple()
+ filterAndOrder()
+ validFilterAndOrder()
+
+ // Can't run this since it throws a fatal error
+ // invalidFilterAndOrder()
+
+ // Enable Offline
+ // Can't run this since it throws a fatal error
+ // enableOffline()
+ listenToOffline()
+ toggleOffline()
+ setupCacheSize()
+
+ // Cursors
+ simpleCursor()
+ snapshotCursor()
+ paginate()
+ multiCursor()
+ }
+
+ func deleteCollection(collection: String) {
+ db.collection(collection).getDocuments() { (querySnapshot, err) in
+ if let err = err {
+ print("Error getting documents: \(err)")
+ return
+ }
- // =======================================================================================
- // ======= https://firebase.google.com/preview/firestore/client/structure-data ===========
- // =======================================================================================
-
-
- private func demonstrateReferences() {
- // [START doc_reference]
- let alovelaceDocumentRef = db.collection("users").document("alovelace")
- // [END doc_reference]
- print(alovelaceDocumentRef)
-
- // [START collection_reference]
- let usersCollectionRef = db.collection("users")
- // [END collection_reference]
- print(usersCollectionRef)
-
- // [START subcollection_reference]
- let messageRef = db
- .collection("rooms").document("roomA")
- .collection("messages").document("message1")
- // [END subcollection_reference]
- print(messageRef)
-
- // [START path_reference]
- let aLovelaceDocumentReference = db.document("users/alovelace")
- // [END path_reference]
- print(aLovelaceDocumentReference)
+ for document in querySnapshot!.documents {
+ print("Deleting \(document.documentID) => \(document.data())")
+ document.reference.delete()
+ }
}
-
- // =======================================================================================
- // ========= https://firebase.google.com/preview/firestore/client/save-data ==============
- // =======================================================================================
-
- private func setDocument() {
- // [START set_document]
- // Add a new document in collection "cities"
- db.collection("cities").document("LA").setData([
- "name": "Los Angeles",
- "state": "CA",
- "country": "USA"
- ]) { err in
- if let err = err {
- print("Error writing document: \(err)")
- } else {
- print("Document successfully written!")
- }
+ }
+
+ private func setupCacheSize() {
+ // [START fs_setup_cache]
+ let settings = Firestore.firestore().settings
+ // Set cache size to 100 MB
+ settings.cacheSettings = PersistentCacheSettings(sizeBytes: 100 * 1024 * 1024 as NSNumber)
+ Firestore.firestore().settings = settings
+ // [END fs_setup_cache]
+ }
+
+ // =======================================================================================
+ // ======== https://firebase.google.com/preview/firestore/client/quickstart ==============
+ // =======================================================================================
+
+ private func addAdaLovelace() async {
+ // [START add_ada_lovelace]
+ // Add a new document with a generated ID
+ do {
+ let ref = try await db.collection("users").addDocument(data: [
+ "first": "Ada",
+ "last": "Lovelace",
+ "born": 1815
+ ])
+ print("Document added with ID: \(ref.documentID)")
+ } catch {
+ print("Error adding document: \(error)")
+ }
+ // [END add_ada_lovelace]
+ }
+
+ private func addAlanTuring() async {
+ // [START add_alan_turing]
+ // Add a second document with a generated ID.
+ do {
+ let ref = try await db.collection("users").addDocument(data: [
+ "first": "Alan",
+ "middle": "Mathison",
+ "last": "Turing",
+ "born": 1912
+ ])
+ print("Document added with ID: \(ref.documentID)")
+ } catch {
+ print("Error adding document: \(error)")
+ }
+ // [END add_alan_turing]
+ }
+
+ private func getCollection() async {
+ // [START get_collection]
+ do {
+ let snapshot = try await db.collection("users").getDocuments()
+ for document in snapshot.documents {
+ print("\(document.documentID) => \(document.data())")
+ }
+ } catch {
+ print("Error getting documents: \(error)")
+ }
+ // [END get_collection]
+ }
+
+ private func listenForUsers() {
+ // [START listen_for_users]
+ // Listen to a query on a collection.
+ //
+ // We will get a first snapshot with the initial results and a new
+ // snapshot each time there is a change in the results.
+ db.collection("users")
+ .whereField("born", isLessThan: 1900)
+ .addSnapshotListener { querySnapshot, error in
+ guard let snapshot = querySnapshot else {
+ print("Error retreiving snapshots \(error!)")
+ return
}
- // [END set_document]
- }
-
- private func dataTypes() {
- // [START data_types]
- let docData: [String: Any] = [
- "stringExample": "Hello world!",
- "booleanExample": true,
- "numberExample": 3.14159265,
- "dateExample": Timestamp(date: Date()),
- "arrayExample": [5, true, "hello"],
- "nullExample": NSNull(),
- "objectExample": [
- "a": 5,
- "b": [
- "nested": "foo"
- ]
- ]
+ print("Current users born before 1900: \(snapshot.documents.map { $0.data() })")
+ }
+ // [END listen_for_users]
+ }
+
+ // =======================================================================================
+ // ======= https://firebase.google.com/preview/firestore/client/structure-data ===========
+ // =======================================================================================
+
+
+ private func demonstrateReferences() {
+ // [START doc_reference]
+ let alovelaceDocumentRef = db.collection("users").document("alovelace")
+ // [END doc_reference]
+ print(alovelaceDocumentRef)
+
+ // [START collection_reference]
+ let usersCollectionRef = db.collection("users")
+ // [END collection_reference]
+ print(usersCollectionRef)
+
+ // [START subcollection_reference]
+ let messageRef = db
+ .collection("rooms").document("roomA")
+ .collection("messages").document("message1")
+ // [END subcollection_reference]
+ print(messageRef)
+
+ // [START path_reference]
+ let aLovelaceDocumentReference = db.document("users/alovelace")
+ // [END path_reference]
+ print(aLovelaceDocumentReference)
+ }
+
+ // =======================================================================================
+ // ========= https://firebase.google.com/preview/firestore/client/save-data ==============
+ // =======================================================================================
+
+ private func setDocument() async {
+ // [START set_document]
+ // Add a new document in collection "cities"
+ do {
+ try await db.collection("cities").document("LA").setData([
+ "name": "Los Angeles",
+ "state": "CA",
+ "country": "USA"
+ ])
+ print("Document successfully written!")
+ } catch {
+ print("Error writing document: \(error)")
+ }
+ // [END set_document]
+ }
+
+ private func setDocumentWithCodable() {
+ // [START set_document_codable]
+ let city = City(name: "Los Angeles",
+ state: "CA",
+ country: "USA",
+ isCapital: false,
+ population: 5000000)
+
+ do {
+ try db.collection("cities").document("LA").setData(from: city)
+ } catch let error {
+ print("Error writing city to Firestore: \(error)")
+ }
+ // [END set_document_codable]
+ }
+
+ private func dataTypes() async {
+ // [START data_types]
+ let docData: [String: Any] = [
+ "stringExample": "Hello world!",
+ "booleanExample": true,
+ "numberExample": 3.14159265,
+ "dateExample": Timestamp(date: Date()),
+ "arrayExample": [5, true, "hello"],
+ "nullExample": NSNull(),
+ "objectExample": [
+ "a": 5,
+ "b": [
+ "nested": "foo"
]
- db.collection("data").document("one").setData(docData) { err in
- if let err = err {
- print("Error writing document: \(err)")
- } else {
- print("Document successfully written!")
- }
+ ]
+ ]
+ do {
+ try await db.collection("data").document("one").setData(docData)
+ print("Document successfully written!")
+ } catch {
+ print("Error writing document: \(error)")
+ }
+ // [END data_types]
+ }
+
+ private func setData() {
+ let data: [String: Any] = [:]
+
+ // [START set_data]
+ db.collection("cities").document("new-city-id").setData(data)
+ // [END set_data]
+ }
+
+ private func addDocument() async {
+ // [START add_document]
+ // Add a new document with a generated id.
+ do {
+ let ref = try await db.collection("cities").addDocument(data: [
+ "name": "Tokyo",
+ "country": "Japan"
+ ])
+ print("Document added with ID: \(ref.documentID)")
+ } catch {
+ print("Error adding document: \(error)")
+ }
+ // [END add_document]
+ }
+
+ private func newDocument() {
+ // [START new_document]
+ let newCityRef = db.collection("cities").document()
+
+ // later...
+ newCityRef.setData([
+ // [START_EXCLUDE]
+ "name": "Some City Name"
+ // [END_EXCLUDE]
+ ])
+ // [END new_document]
+ }
+
+ private func updateDocument() async {
+ // [START update_document]
+ let washingtonRef = db.collection("cities").document("DC")
+
+ // Set the "capital" field of the city 'DC'
+ do {
+ try await washingtonRef.updateData([
+ "capital": true
+ ])
+ print("Document successfully updated")
+ } catch {
+ print("Error updating document: \(error)")
+ }
+ // [END update_document]
+ }
+
+ private func updateDocumentArray() {
+ // [START update_document_array]
+ let washingtonRef = db.collection("cities").document("DC")
+
+ // Atomically add a new region to the "regions" array field.
+ washingtonRef.updateData([
+ "regions": FieldValue.arrayUnion(["greater_virginia"])
+ ])
+
+ // Atomically remove a region from the "regions" array field.
+ washingtonRef.updateData([
+ "regions": FieldValue.arrayRemove(["east_coast"])
+ ])
+ // [END update_document_array]
+ }
+
+ private func updateDocumentIncrement() {
+ // [START update_document-increment]
+ let washingtonRef = db.collection("cities").document("DC")
+
+ // Atomically increment the population of the city by 50.
+ // Note that increment() with no arguments increments by 1.
+ washingtonRef.updateData([
+ "population": FieldValue.increment(Int64(50))
+ ])
+ // [END update_document-increment]
+ }
+
+ private func createIfMissing() {
+ // [START create_if_missing]
+ // Update one field, creating the document if it does not exist.
+ db.collection("cities").document("BJ").setData([ "capital": true ], merge: true)
+ // [END create_if_missing]
+ }
+
+ private func updateDocumentNested() async {
+ // [START update_document_nested]
+ // Create an initial document to update.
+ let frankDocRef = db.collection("users").document("frank")
+ do {
+ try await frankDocRef.setData([
+ "name": "Frank",
+ "favorites": [ "food": "Pizza", "color": "Blue", "subject": "recess" ],
+ "age": 12
+ ])
+
+ // To update age and favorite color:
+ try await frankDocRef.updateData([
+ "age": 13,
+ "favorites.color": "Red"
+ ])
+ print("Document successfully updated")
+ } catch {
+ print("Error updating document: \(error)")
+ }
+ // [END update_document_nested]
+ }
+
+ private func deleteDocument() async {
+ // [START delete_document]
+ do {
+ try await db.collection("cities").document("DC").delete()
+ print("Document successfully removed!")
+ } catch {
+ print("Error removing document: \(error)")
+ }
+ // [END delete_document]
+ }
+
+ private func deleteCollection() {
+ // [START delete_collection]
+ func delete(collection: CollectionReference, batchSize: Int = 100, completion: @escaping (Error?) -> ()) {
+ // Limit query to avoid out-of-memory errors on large collections.
+ // When deleting a collection guaranteed to fit in memory, batching can be avoided entirely.
+ collection.limit(to: batchSize).getDocuments { (docset, error) in
+ // An error occurred.
+ guard let docset = docset else {
+ completion(error)
+ return
}
- // [END data_types]
- }
-
- private func setData() {
- let data: [String: Any] = [:]
-
- // [START set_data]
- db.collection("cities").document("new-city-id").setData(data)
- // [END set_data]
- }
-
- private func addDocument() {
- // [START add_document]
- // Add a new document with a generated id.
- var ref: DocumentReference? = nil
- ref = db.collection("cities").addDocument(data: [
- "name": "Tokyo",
- "country": "Japan"
- ]) { err in
- if let err = err {
- print("Error adding document: \(err)")
- } else {
- print("Document added with ID: \(ref!.documentID)")
- }
+ // There's nothing to delete.
+ guard docset.count > 0 else {
+ completion(nil)
+ return
}
- // [END add_document]
- }
- private func newDocument() {
- // [START new_document]
- let newCityRef = db.collection("cities").document()
-
- // later...
- newCityRef.setData([
- // [START_EXCLUDE]
- "name": "Some City Name"
- // [END_EXCLUDE]
- ])
- // [END new_document]
- }
-
- private func updateDocument() {
- // [START update_document]
- let washingtonRef = db.collection("cities").document("DC")
-
- // Set the "capital" field of the city 'DC'
- washingtonRef.updateData([
- "capital": true
- ]) { err in
- if let err = err {
- print("Error updating document: \(err)")
- } else {
- print("Document successfully updated")
- }
+ let batch = collection.firestore.batch()
+ docset.documents.forEach { batch.deleteDocument($0.reference) }
+
+ batch.commit { (batchError) in
+ if let batchError = batchError {
+ // Stop the deletion process and handle the error. Some elements
+ // may have been deleted.
+ completion(batchError)
+ } else {
+ delete(collection: collection, batchSize: batchSize, completion: completion)
+ }
}
- // [END update_document]
- }
-
- private func updateDocumentArray() {
- // [START update_document_array]
- let washingtonRef = db.collection("cities").document("DC")
-
- // Atomically add a new region to the "regions" array field.
- washingtonRef.updateData([
- "regions": FieldValue.arrayUnion(["greater_virginia"])
- ])
-
- // Atomically remove a region from the "regions" array field.
- washingtonRef.updateData([
- "regions": FieldValue.arrayRemove(["east_coast"])
- ])
- // [END update_document_array]
- }
-
- private func updateDocumentIncrement() {
- // [START update_document-increment]
- let washingtonRef = db.collection("cities").document("DC")
-
- // Atomically incrememnt the population of the city by 50.
- // Note that increment() with no arguments increments by 1.
- washingtonRef.updateData([
- "population": FieldValue.increment(Int64(50))
- ])
- // [END update_document-increment]
- }
-
- private func createIfMissing() {
- // [START create_if_missing]
- // Update one field, creating the document if it does not exist.
- db.collection("cities").document("BJ").setData([ "capital": true ], merge: true)
- // [END create_if_missing]
+ }
}
-
- private func updateDocumentNested() {
- // [START update_document_nested]
- // Create an initial document to update.
- let frankDocRef = db.collection("users").document("frank")
- frankDocRef.setData([
- "name": "Frank",
- "favorites": [ "food": "Pizza", "color": "Blue", "subject": "recess" ],
- "age": 12
- ])
-
- // To update age and favorite color:
- db.collection("users").document("frank").updateData([
- "age": 13,
- "favorites.color": "Red"
- ]) { err in
- if let err = err {
- print("Error updating document: \(err)")
- } else {
- print("Document successfully updated")
- }
+ // [END delete_collection]
+ }
+
+ private func deleteField() async {
+ // [START delete_field]
+ do {
+
+ try await db.collection("cities").document("BJ").updateData([
+ "capital": FieldValue.delete(),
+ ])
+ print("Document successfully updated")
+ } catch {
+ print("Error updating document: \(error)")
+ }
+ // [END delete_field]
+ }
+
+ private func serverTimestamp() async {
+ // [START server_timestamp]
+ do {
+ try await db.collection("objects").document("some-id").updateData([
+ "lastUpdated": FieldValue.serverTimestamp(),
+ ])
+ print("Document successfully updated")
+ } catch {
+ print("Error updating document: \(error)")
+ }
+ // [END server_timestamp]
+ }
+
+ private func serverTimestampOptions() {
+ // [START server_timestamp_options]
+ // Perform an update followed by an immediate read without waiting for the update to
+ // complete. Due to the snapshot options we will get two results: one with an estimated
+ // timestamp and one with a resolved server timestamp.
+ let docRef = db.collection("objects").document("some-id")
+ docRef.updateData(["timestamp": FieldValue.serverTimestamp()])
+
+ docRef.addSnapshotListener { (snapshot, error) in
+ guard let timestamp = snapshot?.data(with: .estimate)?["timestamp"] else { return }
+ guard let pendingWrites = snapshot?.metadata.hasPendingWrites else { return }
+ print("Timestamp: \(timestamp), pending: \(pendingWrites)")
+ }
+ // [END server_timestamp_options]
+ }
+
+ private func simpleTransaction() async {
+ // [START simple_transaction]
+ let sfReference = db.collection("cities").document("SF")
+
+ do {
+ let _ = try await db.runTransaction({ (transaction, errorPointer) -> Any? in
+ let sfDocument: DocumentSnapshot
+ do {
+ try sfDocument = transaction.getDocument(sfReference)
+ } catch let fetchError as NSError {
+ errorPointer?.pointee = fetchError
+ return nil
}
- // [END update_document_nested]
- }
- private func deleteDocument() {
- // [START delete_document]
- db.collection("cities").document("DC").delete() { err in
- if let err = err {
- print("Error removing document: \(err)")
- } else {
- print("Document successfully removed!")
- }
+ guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
+ let error = NSError(
+ domain: "AppErrorDomain",
+ code: -1,
+ userInfo: [
+ NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
+ ]
+ )
+ errorPointer?.pointee = error
+ return nil
}
- // [END delete_document]
- }
- private func deleteCollection() {
- // [START delete_collection]
- func delete(collection: CollectionReference, batchSize: Int = 100, completion: @escaping (Error?) -> ()) {
- // Limit query to avoid out-of-memory errors on large collections.
- // When deleting a collection guaranteed to fit in memory, batching can be avoided entirely.
- collection.limit(to: batchSize).getDocuments { (docset, error) in
- // An error occurred.
- guard let docset = docset else {
- completion(error)
- return
- }
- // There's nothing to delete.
- guard docset.count > 0 else {
- completion(nil)
- return
- }
-
- let batch = collection.firestore.batch()
- docset.documents.forEach { batch.deleteDocument($0.reference) }
-
- batch.commit { (batchError) in
- if let batchError = batchError {
- // Stop the deletion process and handle the error. Some elements
- // may have been deleted.
- completion(batchError)
- } else {
- delete(collection: collection, batchSize: batchSize, completion: completion)
- }
- }
- }
+ // Note: this could be done without a transaction
+ // by updating the population using FieldValue.increment()
+ transaction.updateData(["population": oldPopulation + 1], forDocument: sfReference)
+ return nil
+ })
+ print("Transaction successfully committed!")
+ } catch {
+ print("Transaction failed: \(error)")
+ }
+ // [END simple_transaction]
+ }
+
+ private func transaction() async {
+ // [START transaction]
+ let sfReference = db.collection("cities").document("SF")
+
+ do {
+ let object = try await db.runTransaction({ (transaction, errorPointer) -> Any? in
+ let sfDocument: DocumentSnapshot
+ do {
+ try sfDocument = transaction.getDocument(sfReference)
+ } catch let fetchError as NSError {
+ errorPointer?.pointee = fetchError
+ return nil
}
- // [END delete_collection]
- }
- private func deleteField() {
- // [START delete_field]
- db.collection("cities").document("BJ").updateData([
- "capital": FieldValue.delete(),
- ]) { err in
- if let err = err {
- print("Error updating document: \(err)")
- } else {
- print("Document successfully updated")
- }
+ guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
+ let error = NSError(
+ domain: "AppErrorDomain",
+ code: -1,
+ userInfo: [
+ NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
+ ]
+ )
+ errorPointer?.pointee = error
+ return nil
}
- // [END delete_field]
- }
- private func serverTimestamp() {
- // [START server_timestamp]
- db.collection("objects").document("some-id").updateData([
- "lastUpdated": FieldValue.serverTimestamp(),
- ]) { err in
- if let err = err {
- print("Error updating document: \(err)")
- } else {
- print("Document successfully updated")
- }
+ // Note: this could be done without a transaction
+ // by updating the population using FieldValue.increment()
+ let newPopulation = oldPopulation + 1
+ guard newPopulation <= 1000000 else {
+ let error = NSError(
+ domain: "AppErrorDomain",
+ code: -2,
+ userInfo: [NSLocalizedDescriptionKey: "Population \(newPopulation) too big"]
+ )
+ errorPointer?.pointee = error
+ return nil
}
- // [END server_timestamp]
- }
- private func serverTimestampOptions() {
- // [START server_timestamp_options]
- // Perform an update followed by an immediate read without waiting for the update to
- // complete. Due to the snapshot options we will get two results: one with an estimated
- // timestamp and one with a resolved server timestamp.
- let docRef = db.collection("objects").document("some-id")
- docRef.updateData(["timestamp": FieldValue.serverTimestamp()])
-
- docRef.addSnapshotListener { (snapshot, error) in
- guard let timestamp = snapshot?.data(with: .estimate)?["timestamp"] else { return }
- guard let pendingWrites = snapshot?.metadata.hasPendingWrites else { return }
- print("Timestamp: \(timestamp), pending: \(pendingWrites)")
- }
- // [END server_timestamp_options]
+ transaction.updateData(["population": newPopulation], forDocument: sfReference)
+ return newPopulation
+ })
+ print("Population increased to \(object!)")
+ } catch {
+ print("Error updating population: \(error)")
+ }
+ // [END transaction]
+ }
+
+ private func writeBatch() async {
+ // [START write_batch]
+ // Get new write batch
+ let batch = db.batch()
+
+ // Set the value of 'NYC'
+ let nycRef = db.collection("cities").document("NYC")
+ batch.setData([:], forDocument: nycRef)
+
+ // Update the population of 'SF'
+ let sfRef = db.collection("cities").document("SF")
+ batch.updateData(["population": 1000000 ], forDocument: sfRef)
+
+ // Delete the city 'LA'
+ let laRef = db.collection("cities").document("LA")
+ batch.deleteDocument(laRef)
+
+ // Commit the batch
+ do {
+ try await batch.commit()
+ print("Batch write succeeded.")
+ } catch {
+ print("Error writing batch: \(error)")
+ }
+ // [END write_batch]
+ }
+
+ // =======================================================================================
+ // ======= https://firebase.google.com/preview/firestore/client/retrieve-data ============
+ // =======================================================================================
+
+ private func exampleData() {
+ // [START example_data]
+ let citiesRef = db.collection("cities")
+
+ citiesRef.document("SF").setData([
+ "name": "San Francisco",
+ "state": "CA",
+ "country": "USA",
+ "capital": false,
+ "population": 860000,
+ "regions": ["west_coast", "norcal"]
+ ])
+ citiesRef.document("LA").setData([
+ "name": "Los Angeles",
+ "state": "CA",
+ "country": "USA",
+ "capital": false,
+ "population": 3900000,
+ "regions": ["west_coast", "socal"]
+ ])
+ citiesRef.document("DC").setData([
+ "name": "Washington D.C.",
+ "country": "USA",
+ "capital": true,
+ "population": 680000,
+ "regions": ["east_coast"]
+ ])
+ citiesRef.document("TOK").setData([
+ "name": "Tokyo",
+ "country": "Japan",
+ "capital": true,
+ "population": 9000000,
+ "regions": ["kanto", "honshu"]
+ ])
+ citiesRef.document("BJ").setData([
+ "name": "Beijing",
+ "country": "China",
+ "capital": true,
+ "population": 21500000,
+ "regions": ["jingjinji", "hebei"]
+ ])
+ // [END example_data]
+ }
+
+ private func exampleDataCollectionGroup() {
+ // [START fs_collection_group_query_data_setup]
+ let citiesRef = db.collection("cities")
+
+ var data = ["name": "Golden Gate Bridge", "type": "bridge"]
+ citiesRef.document("SF").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Legion of Honor", "type": "museum"]
+ citiesRef.document("SF").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Griffith Park", "type": "park"]
+ citiesRef.document("LA").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "The Getty", "type": "museum"]
+ citiesRef.document("LA").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Lincoln Memorial", "type": "memorial"]
+ citiesRef.document("DC").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "National Air and Space Museum", "type": "museum"]
+ citiesRef.document("DC").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Ueno Park", "type": "park"]
+ citiesRef.document("TOK").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "National Museum of Nature and Science", "type": "museum"]
+ citiesRef.document("TOK").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Jingshan Park", "type": "park"]
+ citiesRef.document("BJ").collection("landmarks").addDocument(data: data)
+
+ data = ["name": "Beijing Ancient Observatory", "type": "museum"]
+ citiesRef.document("BJ").collection("landmarks").addDocument(data: data)
+ // [END fs_collection_group_query_data_setup]
+ }
+
+ private func getDocument() async {
+ // [START get_document]
+ let docRef = db.collection("cities").document("SF")
+
+ do {
+ let document = try await docRef.getDocument()
+ if document.exists {
+ let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
+ print("Document data: \(dataDescription)")
+ } else {
+ print("Document does not exist")
+ }
+ } catch {
+ print("Error getting document: \(error)")
}
+ // [END get_document]
+ }
- private func simpleTransaction() {
- // [START simple_transaction]
- let sfReference = db.collection("cities").document("SF")
-
- db.runTransaction({ (transaction, errorPointer) -> Any? in
- let sfDocument: DocumentSnapshot
- do {
- try sfDocument = transaction.getDocument(sfReference)
- } catch let fetchError as NSError {
- errorPointer?.pointee = fetchError
- return nil
- }
-
- guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
- let error = NSError(
- domain: "AppErrorDomain",
- code: -1,
- userInfo: [
- NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
- ]
- )
- errorPointer?.pointee = error
- return nil
- }
-
- // Note: this could be done without a transaction
- // by updating the population using FieldValue.increment()
- transaction.updateData(["population": oldPopulation + 1], forDocument: sfReference)
- return nil
- }) { (object, error) in
- if let error = error {
- print("Transaction failed: \(error)")
- } else {
- print("Transaction successfully committed!")
- }
- }
- // [END simple_transaction]
- }
+ private func getDocumentWithOptions() async {
+ // [START get_document_options]
+ let docRef = db.collection("cities").document("SF")
- private func transaction() {
- // [START transaction]
- let sfReference = db.collection("cities").document("SF")
-
- db.runTransaction({ (transaction, errorPointer) -> Any? in
- let sfDocument: DocumentSnapshot
- do {
- try sfDocument = transaction.getDocument(sfReference)
- } catch let fetchError as NSError {
- errorPointer?.pointee = fetchError
- return nil
- }
-
- guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
- let error = NSError(
- domain: "AppErrorDomain",
- code: -1,
- userInfo: [
- NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
- ]
- )
- errorPointer?.pointee = error
- return nil
- }
-
- // Note: this could be done without a transaction
- // by updating the population using FieldValue.increment()
- let newPopulation = oldPopulation + 1
- guard newPopulation <= 1000000 else {
- let error = NSError(
- domain: "AppErrorDomain",
- code: -2,
- userInfo: [NSLocalizedDescriptionKey: "Population \(newPopulation) too big"]
- )
- errorPointer?.pointee = error
- return nil
- }
-
- transaction.updateData(["population": newPopulation], forDocument: sfReference)
- return newPopulation
- }) { (object, error) in
- if let error = error {
- print("Error updating population: \(error)")
- } else {
- print("Population increased to \(object!)")
- }
+ do {
+ // Force the SDK to fetch the document from the cache. Could also specify
+ // FirestoreSource.server or FirestoreSource.default.
+ let document = try await docRef.getDocument(source: .cache)
+ if document.exists {
+ let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
+ print("Cached document data: \(dataDescription)")
+ } else {
+ print("Document does not exist in cache")
+ }
+ } catch {
+ print("Error getting document: \(error)")
+ }
+ // [END get_document_options]
+ }
+
+ private func customClassGetDocument() async {
+ // [START custom_type]
+ let docRef = db.collection("cities").document("BJ")
+
+ do {
+ let city = try await docRef.getDocument(as: City.self)
+ print("City: \(city)")
+ } catch {
+ print("Error decoding city: \(error)")
+ }
+ // [END custom_type]
+ }
+
+ private func listenDocument() {
+ // [START listen_document]
+ db.collection("cities").document("SF")
+ .addSnapshotListener { documentSnapshot, error in
+ guard let document = documentSnapshot else {
+ print("Error fetching document: \(error!)")
+ return
}
- // [END transaction]
- }
-
- private func writeBatch() {
- // [START write_batch]
- // Get new write batch
- let batch = db.batch()
-
- // Set the value of 'NYC'
- let nycRef = db.collection("cities").document("NYC")
- batch.setData([:], forDocument: nycRef)
-
- // Update the population of 'SF'
- let sfRef = db.collection("cities").document("SF")
- batch.updateData(["population": 1000000 ], forDocument: sfRef)
-
- // Delete the city 'LA'
- let laRef = db.collection("cities").document("LA")
- batch.deleteDocument(laRef)
-
- // Commit the batch
- batch.commit() { err in
- if let err = err {
- print("Error writing batch \(err)")
- } else {
- print("Batch write succeeded.")
- }
+ guard let data = document.data() else {
+ print("Document data was empty.")
+ return
}
- // [END write_batch]
- }
-
- // =======================================================================================
- // ======= https://firebase.google.com/preview/firestore/client/retrieve-data ============
- // =======================================================================================
-
- private func exampleData() {
- // [START example_data]
- let citiesRef = db.collection("cities")
-
- citiesRef.document("SF").setData([
- "name": "San Francisco",
- "state": "CA",
- "country": "USA",
- "capital": false,
- "population": 860000,
- "regions": ["west_coast", "norcal"]
- ])
- citiesRef.document("LA").setData([
- "name": "Los Angeles",
- "state": "CA",
- "country": "USA",
- "capital": false,
- "population": 3900000,
- "regions": ["west_coast", "socal"]
- ])
- citiesRef.document("DC").setData([
- "name": "Washington D.C.",
- "country": "USA",
- "capital": true,
- "population": 680000,
- "regions": ["east_coast"]
- ])
- citiesRef.document("TOK").setData([
- "name": "Tokyo",
- "country": "Japan",
- "capital": true,
- "population": 9000000,
- "regions": ["kanto", "honshu"]
- ])
- citiesRef.document("BJ").setData([
- "name": "Beijing",
- "country": "China",
- "capital": true,
- "population": 21500000,
- "regions": ["jingjinji", "hebei"]
- ])
- // [END example_data]
- }
-
- private func exampleDataCollectionGroup() {
- // [START fs_collection_group_query_data_setup]
- let citiesRef = db.collection("cities")
-
- var data = ["name": "Golden Gate Bridge", "type": "bridge"]
- citiesRef.document("SF").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Legion of Honor", "type": "museum"]
- citiesRef.document("SF").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Griffith Park", "type": "park"]
- citiesRef.document("LA").collection("landmarks").addDocument(data: data)
-
- data = ["name": "The Getty", "type": "museum"]
- citiesRef.document("LA").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Lincoln Memorial", "type": "memorial"]
- citiesRef.document("DC").collection("landmarks").addDocument(data: data)
-
- data = ["name": "National Air and Space Museum", "type": "museum"]
- citiesRef.document("DC").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Ueno Park", "type": "park"]
- citiesRef.document("TOK").collection("landmarks").addDocument(data: data)
-
- data = ["name": "National Museum of Nature and Science", "type": "museum"]
- citiesRef.document("TOK").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Jingshan Park", "type": "park"]
- citiesRef.document("BJ").collection("landmarks").addDocument(data: data)
-
- data = ["name": "Beijing Ancient Observatory", "type": "museum"]
- citiesRef.document("BJ").collection("landmarks").addDocument(data: data)
- // [END fs_collection_group_query_data_setup]
- }
-
- private func getDocument() {
- // [START get_document]
- let docRef = db.collection("cities").document("SF")
-
- docRef.getDocument { (document, error) in
- if let document = document, document.exists {
- let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
- print("Document data: \(dataDescription)")
- } else {
- print("Document does not exist")
- }
+ print("Current data: \(data)")
+ }
+ // [END listen_document]
+ }
+
+ private func listenDocumentLocal() {
+ // [START listen_document_local]
+ db.collection("cities").document("SF")
+ .addSnapshotListener { documentSnapshot, error in
+ guard let document = documentSnapshot else {
+ print("Error fetching document: \(error!)")
+ return
}
- // [END get_document]
- }
-
- private func getDocumentWithOptions() {
- // [START get_document_options]
- let docRef = db.collection("cities").document("SF")
-
- // Force the SDK to fetch the document from the cache. Could also specify
- // FirestoreSource.server or FirestoreSource.default.
- docRef.getDocument(source: .cache) { (document, error) in
- if let document = document {
- let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
- print("Cached document data: \(dataDescription)")
- } else {
- print("Document does not exist in cache")
+ let source = document.metadata.hasPendingWrites ? "Local" : "Server"
+ print("\(source) data: \(document.data() ?? [:])")
+ }
+ // [END listen_document_local]
+ }
+
+ private func listenWithMetadata() {
+ // [START listen_with_metadata]
+ // Listen to document metadata.
+ db.collection("cities").document("SF")
+ .addSnapshotListener(includeMetadataChanges: true) { documentSnapshot, error in
+ // ...
+ }
+ // [END listen_with_metadata]
+ }
+
+ private func getMultiple() async {
+ // [START get_multiple]
+ do {
+ let querySnapshot = try await db.collection("cities").whereField("capital", isEqualTo: true)
+ .getDocuments()
+ for document in querySnapshot.documents {
+ print("\(document.documentID) => \(document.data())")
+ }
+ } catch {
+ print("Error getting documents: \(error)")
+ }
+ // [END get_multiple]
+ }
+
+ private func getMultipleAll() async {
+ // [START get_multiple_all]
+ do {
+ let querySnapshot = try await db.collection("cities").getDocuments()
+ for document in querySnapshot.documents {
+ print("\(document.documentID) => \(document.data())")
+ }
+ } catch {
+ print("Error getting documents: \(error)")
+ }
+ // [END get_multiple_all]
+ }
+
+ private func getMultipleAllSubcollection() async {
+ // [START get_multiple_all_subcollection]
+ do {
+ let querySnapshot = try await db.collection("cities/SF/landmarks").getDocuments()
+ for document in querySnapshot.documents {
+ print("\(document.documentID) => \(document.data())")
+ }
+ } catch {
+ print("Error getting documents: \(error)")
+ }
+ // [END get_multiple_all_subcollection]
+ }
+
+ private func listenMultiple() {
+ // [START listen_multiple]
+ db.collection("cities").whereField("state", isEqualTo: "CA")
+ .addSnapshotListener { querySnapshot, error in
+ guard let documents = querySnapshot?.documents else {
+ print("Error fetching documents: \(error!)")
+ return
}
+ let cities = documents.compactMap { $0["name"] }
+ print("Current cities in CA: \(cities)")
}
- // [END get_document_options]
- }
-
- private func customClassGetDocument() {
- // [START custom_type]
- let docRef = db.collection("cities").document("BJ")
-
- docRef.getDocument { (document, error) in
- if let city = document.flatMap({
- $0.data().flatMap({ (data) in
- return City(dictionary: data)
- })
- }) {
- print("City: \(city)")
- } else {
- print("Document does not exist")
- }
+ // [END listen_multiple]
+ }
+
+ private func listenDiffs() {
+ // [START listen_diffs]
+ db.collection("cities").whereField("state", isEqualTo: "CA")
+ .addSnapshotListener { querySnapshot, error in
+ guard let snapshot = querySnapshot else {
+ print("Error fetching snapshots: \(error!)")
+ return
}
- // [END custom_type]
- }
-
- private func listenDocument() {
- // [START listen_document]
- db.collection("cities").document("SF")
- .addSnapshotListener { documentSnapshot, error in
- guard let document = documentSnapshot else {
- print("Error fetching document: \(error!)")
- return
- }
- guard let data = document.data() else {
- print("Document data was empty.")
- return
- }
- print("Current data: \(data)")
- }
- // [END listen_document]
- }
-
- private func listenDocumentLocal() {
- // [START listen_document_local]
- db.collection("cities").document("SF")
- .addSnapshotListener { documentSnapshot, error in
- guard let document = documentSnapshot else {
- print("Error fetching document: \(error!)")
- return
- }
- let source = document.metadata.hasPendingWrites ? "Local" : "Server"
- print("\(source) data: \(document.data() ?? [:])")
- }
- // [END listen_document_local]
- }
-
- private func listenWithMetadata() {
- // [START listen_with_metadata]
- // Listen to document metadata.
- db.collection("cities").document("SF")
- .addSnapshotListener(includeMetadataChanges: true) { documentSnapshot, error in
- // ...
- }
- // [END listen_with_metadata]
- }
-
- private func getMultiple() {
- // [START get_multiple]
- db.collection("cities").whereField("capital", isEqualTo: true)
- .getDocuments() { (querySnapshot, err) in
- if let err = err {
- print("Error getting documents: \(err)")
- } else {
- for document in querySnapshot!.documents {
- print("\(document.documentID) => \(document.data())")
- }
- }
+ snapshot.documentChanges.forEach { diff in
+ if (diff.type == .added) {
+ print("New city: \(diff.document.data())")
+ }
+ if (diff.type == .modified) {
+ print("Modified city: \(diff.document.data())")
+ }
+ if (diff.type == .removed) {
+ print("Removed city: \(diff.document.data())")
+ }
}
- // [END get_multiple]
- }
-
- private func getMultipleAll() {
- // [START get_multiple_all]
- db.collection("cities").getDocuments() { (querySnapshot, err) in
- if let err = err {
- print("Error getting documents: \(err)")
- } else {
- for document in querySnapshot!.documents {
- print("\(document.documentID) => \(document.data())")
- }
- }
+ }
+ // [END listen_diffs]
+ }
+
+ private func listenState() {
+ // [START listen_state]
+ db.collection("cities").whereField("state", isEqualTo: "CA")
+ .addSnapshotListener { querySnapshot, error in
+ guard let snapshot = querySnapshot else {
+ print("Error fetching documents: \(error!)")
+ return
}
- // [END get_multiple_all]
- }
-
- private func listenMultiple() {
- // [START listen_multiple]
- db.collection("cities").whereField("state", isEqualTo: "CA")
- .addSnapshotListener { querySnapshot, error in
- guard let documents = querySnapshot?.documents else {
- print("Error fetching documents: \(error!)")
- return
- }
- let cities = documents.map { $0["name"]! }
- print("Current cities in CA: \(cities)")
- }
- // [END listen_multiple]
- }
-
- private func listenDiffs() {
- // [START listen_diffs]
- db.collection("cities").whereField("state", isEqualTo: "CA")
- .addSnapshotListener { querySnapshot, error in
- guard let snapshot = querySnapshot else {
- print("Error fetching snapshots: \(error!)")
- return
- }
- snapshot.documentChanges.forEach { diff in
- if (diff.type == .added) {
- print("New city: \(diff.document.data())")
- }
- if (diff.type == .modified) {
- print("Modified city: \(diff.document.data())")
- }
- if (diff.type == .removed) {
- print("Removed city: \(diff.document.data())")
- }
- }
- }
- // [END listen_diffs]
- }
-
- private func listenState() {
- // [START listen_state]
- db.collection("cities").whereField("state", isEqualTo: "CA")
- .addSnapshotListener { querySnapshot, error in
- guard let snapshot = querySnapshot else {
- print("Error fetching documents: \(error!)")
- return
- }
- snapshot.documentChanges.forEach { diff in
- if (diff.type == .added) {
- print("New city: \(diff.document.data())")
- }
- }
-
- if !snapshot.metadata.isFromCache {
- print("Synced with server state.")
- }
- }
- // [END listen_state]
- }
-
- private func detachListener() {
- // [START detach_listener]
- let listener = db.collection("cities").addSnapshotListener { querySnapshot, error in
- // [START_EXCLUDE]
- // [END_EXCLUDE]
+ snapshot.documentChanges.forEach { diff in
+ if (diff.type == .added) {
+ print("New city: \(diff.document.data())")
+ }
}
- // ...
-
- // Stop listening to changes
- listener.remove()
- // [END detach_listener]
- }
-
- private func handleListenErrors() {
- // [START handle_listen_errors]
- db.collection("cities")
- .addSnapshotListener { querySnapshot, error in
- if let error = error {
- print("Error retreiving collection: \(error)")
- }
- }
- // [END handle_listen_errors]
- }
-
- // =======================================================================================
- // ======== https://firebase.google.com/preview/firestore/client/query-data ==============
- // =======================================================================================
-
- private func simpleQueries() {
- // [START simple_queries]
- // Create a reference to the cities collection
- let citiesRef = db.collection("cities")
-
- // Create a query against the collection.
- let query = citiesRef.whereField("state", isEqualTo: "CA")
- // [END simple_queries]
-
- print(query)
- }
-
- private func exampleFilters() {
- let citiesRef = db.collection("cities")
-
- // [START example_filters]
- citiesRef.whereField("state", isEqualTo: "CA")
- citiesRef.whereField("population", isLessThan: 100000)
- citiesRef.whereField("name", isGreaterThanOrEqualTo: "San Francisco")
- // [END example_filters]
- }
-
- private func onlyCapitals() {
- // [START only_capitals]
- let capitalCities = db.collection("cities").whereField("capital", isEqualTo: true)
- // [END only_capitals]
- print(capitalCities)
- }
-
- private func arrayContainsFilter() {
- let citiesRef = db.collection("cities")
-
- // [START array_contains_filter]
- citiesRef
- .whereField("regions", arrayContains: "west_coast")
- // [END array_contains_filter]
- }
-
- private func chainFilters() {
- let citiesRef = db.collection("cities")
-
- // [START chain_filters]
- citiesRef
- .whereField("state", isEqualTo: "CO")
- .whereField("name", isEqualTo: "Denver")
- citiesRef
- .whereField("state", isEqualTo: "CA")
- .whereField("population", isLessThan: 1000000)
- // [END chain_filters]
- }
-
- private func validRangeFilters() {
- let citiesRef = db.collection("cities")
-
- // [START valid_range_filters]
- citiesRef
- .whereField("state", isGreaterThanOrEqualTo: "CA")
- .whereField("state", isLessThanOrEqualTo: "IN")
- citiesRef
- .whereField("state", isEqualTo: "CA")
- .whereField("population", isGreaterThan: 1000000)
- // [END valid_range_filters]
- }
-
- private func invalidRangeFilters() throws {
- let citiesRef = db.collection("cities")
-
- // [START invalid_range_filters]
- citiesRef
- .whereField("state", isGreaterThanOrEqualTo: "CA")
- .whereField("population", isGreaterThan: 1000000)
- // [END invalid_range_filters]
- }
-
- private func orderAndLimit() {
- let citiesRef = db.collection("cities")
-
- // [START order_and_limit]
- citiesRef.order(by: "name").limit(to: 3)
- // [END order_and_limit]
- }
-
- private func orderAndLimitDesc() {
- let citiesRef = db.collection("cities")
-
- // [START order_and_limit_desc]
- citiesRef.order(by: "name", descending: true).limit(to: 3)
- // [END order_and_limit_desc]
- }
-
- private func orderMultiple() {
- let citiesRef = db.collection("cities")
-
- // [START order_multiple]
- citiesRef
- .order(by: "state")
- .order(by: "population", descending: true)
- // [END order_multiple]
- }
-
- private func filterAndOrder() {
- let citiesRef = db.collection("cities")
-
- // [START filter_and_order]
- citiesRef
- .whereField("population", isGreaterThan: 100000)
- .order(by: "population")
- .limit(to: 2)
- // [END filter_and_order]
- }
-
- private func validFilterAndOrder() {
- let citiesRef = db.collection("cities")
-
- // [START valid_filter_and_order]
- citiesRef
- .whereField("population", isGreaterThan: 100000)
- .order(by: "population")
- // [END valid_filter_and_order]
- }
-
- private func invalidFilterAndOrder() throws {
- let citiesRef = db.collection("cities")
+ if !snapshot.metadata.isFromCache {
+ print("Synced with server state.")
+ }
+ }
+ // [END listen_state]
+ }
- // [START invalid_filter_and_order]
- citiesRef
- .whereField("population", isGreaterThan: 100000)
- .order(by: "country")
- // [END invalid_filter_and_order]
+ private func detachListener() {
+ // [START detach_listener]
+ let listener = db.collection("cities").addSnapshotListener { querySnapshot, error in
+ // [START_EXCLUDE]
+ // [END_EXCLUDE]
}
+ // ...
- // =======================================================================================
- // ====== https://firebase.google.com/preview/firestore/client/enable-offline ============
- // =======================================================================================
-
- private func enableOffline() {
- // [START enable_offline]
- let settings = FirestoreSettings()
- settings.isPersistenceEnabled = true
-
- // Any additional options
- // ...
+ // Stop listening to changes
+ listener.remove()
+ // [END detach_listener]
+ }
- // Enable offline data persistence
- let db = Firestore.firestore()
- db.settings = settings
- // [END enable_offline]
- }
-
- private func listenToOffline() {
- let db = Firestore.firestore()
- // [START listen_to_offline]
- // Listen to metadata updates to receive a server snapshot even if
- // the data is the same as the cached data.
- db.collection("cities").whereField("state", isEqualTo: "CA")
- .addSnapshotListener(includeMetadataChanges: true) { querySnapshot, error in
- guard let snapshot = querySnapshot else {
- print("Error retreiving snapshot: \(error!)")
- return
- }
-
- for diff in snapshot.documentChanges {
- if diff.type == .added {
- print("New city: \(diff.document.data())")
- }
- }
-
- let source = snapshot.metadata.isFromCache ? "local cache" : "server"
- print("Metadata: Data fetched from \(source)")
+ private func handleListenErrors() {
+ // [START handle_listen_errors]
+ db.collection("cities")
+ .addSnapshotListener { querySnapshot, error in
+ if let error = error {
+ print("Error retreiving collection: \(error)")
}
- // [END listen_to_offline]
- }
-
- private func toggleOffline() {
- // [START disable_network]
- Firestore.firestore().disableNetwork { (error) in
- // Do offline things
- // ...
+ }
+ // [END handle_listen_errors]
+ }
+
+ // =======================================================================================
+ // ======== https://firebase.google.com/preview/firestore/client/query-data ==============
+ // =======================================================================================
+
+ private func simpleQueries() {
+ // [START simple_queries]
+ // Create a reference to the cities collection
+ let citiesRef = db.collection("cities")
+
+ // Create a query against the collection.
+ let query = citiesRef.whereField("state", isEqualTo: "CA")
+ // [END simple_queries]
+
+ // [START simple_query_not_equal]
+ let notEqualQuery = citiesRef.whereField("capital", isNotEqualTo: false)
+ // [END simple_query_not_equal]
+
+ print(query)
+ }
+
+ private func exampleFilters() {
+ let citiesRef = db.collection("cities")
+
+ // [START example_filters]
+ let stateQuery = citiesRef.whereField("state", isEqualTo: "CA")
+ let populationQuery = citiesRef.whereField("population", isLessThan: 100000)
+ let nameQuery = citiesRef.whereField("name", isGreaterThanOrEqualTo: "San Francisco")
+ // [END example_filters]
+ }
+
+ private func onlyCapitals() {
+ // [START only_capitals]
+ let capitalCities = db.collection("cities").whereField("capital", isEqualTo: true)
+ // [END only_capitals]
+ print(capitalCities)
+ }
+
+ private func arrayContainsFilter() {
+ let citiesRef = db.collection("cities")
+
+ // [START array_contains_filter]
+ citiesRef
+ .whereField("regions", arrayContains: "west_coast")
+ // [END array_contains_filter]
+ }
+
+ private func chainFilters() {
+ let citiesRef = db.collection("cities")
+
+ // [START chain_filters]
+ citiesRef
+ .whereField("state", isEqualTo: "CO")
+ .whereField("name", isEqualTo: "Denver")
+ citiesRef
+ .whereField("state", isEqualTo: "CA")
+ .whereField("population", isLessThan: 1000000)
+ // [END chain_filters]
+ }
+
+ private func validRangeFilters() {
+ let citiesRef = db.collection("cities")
+
+ // [START valid_range_filters]
+ citiesRef
+ .whereField("state", isGreaterThanOrEqualTo: "CA")
+ .whereField("state", isLessThanOrEqualTo: "IN")
+ citiesRef
+ .whereField("state", isEqualTo: "CA")
+ .whereField("population", isGreaterThan: 1000000)
+ // [END valid_range_filters]
+ }
+
+ private func invalidRangeFilters() throws {
+ let citiesRef = db.collection("cities")
+
+ // [START invalid_range_filters]
+ citiesRef
+ .whereField("state", isGreaterThanOrEqualTo: "CA")
+ .whereField("population", isGreaterThan: 1000000)
+ // [END invalid_range_filters]
+ }
+
+ private func orderAndLimit() {
+ let citiesRef = db.collection("cities")
+
+ // [START order_and_limit]
+ citiesRef.order(by: "name").limit(to: 3)
+ // [END order_and_limit]
+ }
+
+ private func orderAndLimitDesc() {
+ let citiesRef = db.collection("cities")
+
+ // [START order_and_limit_desc]
+ citiesRef.order(by: "name", descending: true).limit(to: 3)
+ // [END order_and_limit_desc]
+ }
+
+ private func orderMultiple() {
+ let citiesRef = db.collection("cities")
+
+ // [START order_multiple]
+ citiesRef
+ .order(by: "state")
+ .order(by: "population", descending: true)
+ // [END order_multiple]
+ }
+
+ private func filterAndOrder() {
+ let citiesRef = db.collection("cities")
+
+ // [START filter_and_order]
+ citiesRef
+ .whereField("population", isGreaterThan: 100000)
+ .order(by: "population")
+ .limit(to: 2)
+ // [END filter_and_order]
+ }
+
+ private func validFilterAndOrder() {
+ let citiesRef = db.collection("cities")
+
+ // [START valid_filter_and_order]
+ citiesRef
+ .whereField("population", isGreaterThan: 100000)
+ .order(by: "population")
+ // [END valid_filter_and_order]
+ }
+
+ private func invalidFilterAndOrder() throws {
+ let citiesRef = db.collection("cities")
+
+ // [START invalid_filter_and_order]
+ citiesRef
+ .whereField("population", isGreaterThan: 100000)
+ .order(by: "country")
+ // [END invalid_filter_and_order]
+ }
+
+ private func arrayContainsAnyQueries() {
+ // [START array_contains_any_filter]
+ let citiesRef = db.collection("cities")
+ citiesRef.whereField("regions", arrayContainsAny: ["west_coast", "east_coast"])
+ // [END array_contains_any_filter]
+ }
+
+ private func inQueries() {
+ // [START in_filter]
+ let citiesRef = db.collection("cities")
+
+ citiesRef.whereField("country", in: ["USA", "Japan"])
+ // [END in_filter]
+
+ // [START in_filter_with_array]
+ citiesRef.whereField("regions", in: [["west_coast"], ["east_coast"]])
+ // [END in_filter_with_array]
+
+ // [START not_in_filter]
+ citiesRef.whereField("country", notIn: ["USA", "Japan"])
+ // [END not_in_filter]
+ }
+
+ // =======================================================================================
+ // ====== https://firebase.google.com/preview/firestore/client/enable-offline ============
+ // =======================================================================================
+
+ private func enableOffline() {
+ // [START enable_offline]
+ let settings = FirestoreSettings()
+
+ // Use memory-only cache
+ settings.cacheSettings =
+ MemoryCacheSettings(garbageCollectorSettings: MemoryLRUGCSettings())
+
+ // Use persistent disk cache, with 100 MB cache size
+ settings.cacheSettings = PersistentCacheSettings(sizeBytes: 100 * 1024 * 1024 as NSNumber)
+
+ // Any additional options
+ // ...
+
+ // Enable offline data persistence
+ let db = Firestore.firestore()
+ db.settings = settings
+ // [END enable_offline]
+ }
+
+ private func listenToOffline() {
+ let db = Firestore.firestore()
+ // [START listen_to_offline]
+ // Listen to metadata updates to receive a server snapshot even if
+ // the data is the same as the cached data.
+ db.collection("cities").whereField("state", isEqualTo: "CA")
+ .addSnapshotListener(includeMetadataChanges: true) { querySnapshot, error in
+ guard let snapshot = querySnapshot else {
+ print("Error retreiving snapshot: \(error!)")
+ return
}
- // [END disable_network]
- // [START enable_network]
- Firestore.firestore().enableNetwork { (error) in
- // Do online things
- // ...
+ for diff in snapshot.documentChanges {
+ if diff.type == .added {
+ print("New city: \(diff.document.data())")
+ }
}
- // [END enable_network]
- }
- // =======================================================================================
- // ====== https://firebase.google.com/preview/firestore/client/cursors ===================
- // =======================================================================================
-
- private func simpleCursor() {
- let db = Firestore.firestore()
-
- // [START cursor_greater_than]
- // Get all cities with population over one million, ordered by population.
- db.collection("cities")
- .order(by: "population")
- .start(at: [1000000])
- // [END cursor_greater_than]
-
- // [START cursor_less_than]
- // Get all cities with population less than one million, ordered by population.
- db.collection("cities")
- .order(by: "population")
- .end(at: [1000000])
- // [END cursor_less_than]
- }
-
- private func snapshotCursor() {
- let db = Firestore.firestore()
-
- // [START snapshot_cursor]
- db.collection("cities")
- .document("SF")
- .addSnapshotListener { (document, error) in
- guard let document = document else {
- print("Error retreving cities: \(error.debugDescription)")
- return
- }
-
- // Get all cities with a population greater than or equal to San Francisco.
- let sfSizeOrBigger = db.collection("cities")
- .order(by: "population")
- .start(atDocument: document)
+ let source = snapshot.metadata.isFromCache ? "local cache" : "server"
+ print("Metadata: Data fetched from \(source)")
+ }
+ // [END listen_to_offline]
+ }
+
+ private func toggleOffline() {
+ // [START disable_network]
+ Firestore.firestore().disableNetwork { (error) in
+ // Do offline things
+ // ...
+ }
+ // [END disable_network]
+
+ // [START enable_network]
+ Firestore.firestore().enableNetwork { (error) in
+ // Do online things
+ // ...
+ }
+ // [END enable_network]
+ }
+
+ // =======================================================================================
+ // ====== https://firebase.google.com/preview/firestore/client/cursors ===================
+ // =======================================================================================
+
+ private func simpleCursor() {
+ let db = Firestore.firestore()
+
+ // [START cursor_greater_than]
+ // Get all cities with population over one million, ordered by population.
+ db.collection("cities")
+ .order(by: "population")
+ .start(at: [1000000])
+ // [END cursor_greater_than]
+
+ // [START cursor_less_than]
+ // Get all cities with population less than one million, ordered by population.
+ db.collection("cities")
+ .order(by: "population")
+ .end(at: [1000000])
+ // [END cursor_less_than]
+ }
+
+ private func snapshotCursor() {
+ let db = Firestore.firestore()
+
+ // [START snapshot_cursor]
+ db.collection("cities")
+ .document("SF")
+ .addSnapshotListener { (document, error) in
+ guard let document = document else {
+ print("Error retreving cities: \(error.debugDescription)")
+ return
}
- // [END snapshot_cursor]
- }
- private func paginate() {
- let db = Firestore.firestore()
-
- // [START paginate]
- // Construct query for first 25 cities, ordered by population
- let first = db.collection("cities")
- .order(by: "population")
- .limit(to: 25)
-
- first.addSnapshotListener { (snapshot, error) in
- guard let snapshot = snapshot else {
- print("Error retreving cities: \(error.debugDescription)")
- return
- }
-
- guard let lastSnapshot = snapshot.documents.last else {
- // The collection is empty.
- return
- }
-
- // Construct a new query starting after this document,
- // retrieving the next 25 cities.
- let next = db.collection("cities")
- .order(by: "population")
- .start(afterDocument: lastSnapshot)
-
- // Use the query for pagination.
- // ...
- }
- // [END paginate]
- }
+ // Get all cities with a population greater than or equal to San Francisco.
+ let sfSizeOrBigger = db.collection("cities")
+ .order(by: "population")
+ .start(atDocument: document)
+ }
+ // [END snapshot_cursor]
+ }
+
+ private func paginate() {
+ let db = Firestore.firestore()
+
+ // [START paginate]
+ // Construct query for first 25 cities, ordered by population
+ let first = db.collection("cities")
+ .order(by: "population")
+ .limit(to: 25)
+
+ first.addSnapshotListener { (snapshot, error) in
+ guard let snapshot = snapshot else {
+ print("Error retreving cities: \(error.debugDescription)")
+ return
+ }
- private func multiCursor() {
- let db = Firestore.firestore()
-
- // [START multi_cursor]
- // Will return all Springfields
- db.collection("cities")
- .order(by: "name")
- .order(by: "state")
- .start(at: ["Springfield"])
-
- // Will return "Springfield, Missouri" and "Springfield, Wisconsin"
- db.collection("cities")
- .order(by: "name")
- .order(by: "state")
- .start(at: ["Springfield", "Missouri"])
- // [END multi_cursor]
- }
+ guard let lastSnapshot = snapshot.documents.last else {
+ // The collection is empty.
+ return
+ }
- private func collectionGroupQuery() {
- // [START fs_collection_group_query]
- db.collectionGroup("landmarks").whereField("type", isEqualTo: "museum").getDocuments { (snapshot, error) in
- // [START_EXCLUDE]
- print(snapshot?.documents.count ?? 0)
- // [END_EXCLUDE]
- }
- // [END fs_collection_group_query]
- }
+ // Construct a new query starting after this document,
+ // retrieving the next 25 cities.
+ let next = db.collection("cities")
+ .order(by: "population")
+ .start(afterDocument: lastSnapshot)
+
+ // Use the query for pagination.
+ // ...
+ }
+ // [END paginate]
+ }
+
+ private func multiCursor() {
+ let db = Firestore.firestore()
+
+ // [START multi_cursor]
+ // Will return all Springfields
+ db.collection("cities")
+ .order(by: "name")
+ .order(by: "state")
+ .start(at: ["Springfield"])
+
+ // Will return "Springfield, Missouri" and "Springfield, Wisconsin"
+ db.collection("cities")
+ .order(by: "name")
+ .order(by: "state")
+ .start(at: ["Springfield", "Missouri"])
+ // [END multi_cursor]
+ }
+
+ private func collectionGroupQuery() {
+ // [START fs_collection_group_query]
+ db.collectionGroup("landmarks").whereField("type", isEqualTo: "museum").getDocuments { (snapshot, error) in
+ // [START_EXCLUDE]
+ print(snapshot?.documents.count ?? 0)
+ // [END_EXCLUDE]
+ }
+ // [END fs_collection_group_query]
+ }
+
+ private func emulatorSettings() {
+ // [START fs_emulator_connect]
+ let settings = Firestore.firestore().settings
+ settings.host = "127.0.0.1:8080"
+ settings.cacheSettings = MemoryCacheSettings()
+ settings.isSSLEnabled = false
+ Firestore.firestore().settings = settings
+ // [END fs_emulator_connect]
+ }
+
+ // MARK: Aggregation queries
+ private func countAggregateCollection() async {
+ // [START count_aggregate_collection]
+ let query = db.collection("cities")
+ let countQuery = query.count
+ do {
+ let snapshot = try await countQuery.getAggregation(source: .server)
+ print(snapshot.count)
+ } catch {
+ print(error)
+ }
+ // [END count_aggregate_collection]
+ }
+
+ private func countAggregateQuery() async {
+ // [START count_aggregate_query]
+ let query = db.collection("cities").whereField("state", isEqualTo: "CA")
+ let countQuery = query.count
+ do {
+ let snapshot = try await countQuery.getAggregation(source: .server)
+ print(snapshot.count)
+ } catch {
+ print(error)
+ }
+ // [END count_aggregate_query]
+ }
+
+ private func sumAggregateCollection() async {
+ // [START sum_aggregate_collection]
+ let query = db.collection("cities")
+ let aggregateQuery = query.aggregate([AggregateField.sum("population")])
+ do {
+ let snapshot = try await aggregateQuery.getAggregation(source: .server)
+ print(snapshot.get(AggregateField.sum("population")))
+ } catch {
+ print(error)
+ }
+ // [END sum_aggregate_collection]
+ }
+
+ private func sumAggregateQuery() async {
+ // [START sum_aggregate_query]
+ let query = db.collection("cities").whereField("capital", isEqualTo: true)
+ let aggregateQuery = query.aggregate([AggregateField.sum("population")])
+ do {
+ let snapshot = try await aggregateQuery.getAggregation(source: .server)
+ print(snapshot.get(AggregateField.sum("population")))
+ } catch {
+ print(error)
+ }
+ // [END sum_aggregate_query]
+ }
+
+ private func averageAggregateCollection() async {
+ // [START average_aggregate_collection]
+ let query = db.collection("cities")
+ let aggregateQuery = query.aggregate([AggregateField.average("population")])
+ do {
+ let snapshot = try await aggregateQuery.getAggregation(source: .server)
+ print(snapshot.get(AggregateField.average("population")))
+ } catch {
+ print(error)
+ }
+ // [END average_aggregate_collection]
+ }
+
+ private func averageAggregateQuery() async {
+ // [START average_aggregate_query]
+ let query = db.collection("cities").whereField("capital", isEqualTo: true)
+ let aggregateQuery = query.aggregate([AggregateField.average("population")])
+ do {
+ let snapshot = try await aggregateQuery.getAggregation(source: .server)
+ print(snapshot.get(AggregateField.average("population")))
+ } catch {
+ print(error)
+ }
+ // [END average_aggregate_query]
+ }
+
+ private func multiAggregateCollection() async {
+ // [START multi_aggregate_collection]
+ let query = db.collection("cities")
+ let aggregateQuery = query.aggregate([
+ AggregateField.count(),
+ AggregateField.sum("population"),
+ AggregateField.average("population")])
+ do {
+ let snapshot = try await aggregateQuery.getAggregation(source: .server)
+ print("Count: \(snapshot.get(AggregateField.count()))")
+ print("Sum: \(snapshot.get(AggregateField.sum("population")))")
+ print("Average: \(snapshot.get(AggregateField.average("population")))")
+ } catch {
+ print(error)
+ }
+ // [END multi_aggregate_collection]
+ }
+
+ private func orQuery() {
+ // [START or_query]
+ let query = db.collection("cities").whereFilter(Filter.andFilter([
+ Filter.whereField("state", isEqualTo: "CA"),
+ Filter.orFilter([
+ Filter.whereField("capital", isEqualTo: true),
+ Filter.whereField("population", isGreaterOrEqualTo: 1000000)
+ ])
+ ]))
+ // [END or_query]
+ }
+
+ private func orQueryDisjunctions() {
+ let collection = db.collection("cities")
+
+ // [START one_disjunction]
+ collection.whereField("a", isEqualTo: 1)
+ // [END one_disjunction]
+
+ // [START two_disjunctions]
+ collection.whereFilter(Filter.orFilter([
+ Filter.whereField("a", isEqualTo: 1),
+ Filter.whereField("b", isEqualTo: 2)
+ ]))
+ // [END two_disjunctions]
+
+ // [START four_disjunctions]
+ collection.whereFilter(Filter.orFilter([
+ Filter.andFilter([
+ Filter.whereField("a", isEqualTo: 1),
+ Filter.whereField("c", isEqualTo: 3)
+ ]),
+ Filter.andFilter([
+ Filter.whereField("a", isEqualTo: 1),
+ Filter.whereField("d", isEqualTo: 4)
+ ]),
+ Filter.andFilter([
+ Filter.whereField("b", isEqualTo: 2),
+ Filter.whereField("c", isEqualTo: 3)
+ ]),
+ Filter.andFilter([
+ Filter.whereField("b", isEqualTo: 2),
+ Filter.whereField("d", isEqualTo: 4)
+ ])
+ ]))
+ // [END four_disjunctions]
+
+ // [START four_disjunctions_compact]
+ collection.whereFilter(Filter.andFilter([
+ Filter.orFilter([
+ Filter.whereField("a", isEqualTo: 1),
+ Filter.whereField("b", isEqualTo: 2)
+ ]),
+ Filter.orFilter([
+ Filter.whereField("c", isEqualTo: 3),
+ Filter.whereField("d", isEqualTo: 4)
+ ]),
+ ]))
+ // [END four_disjunctions_compact]
+
+ // [START 20_disjunctions]
+ collection.whereFilter(Filter.orFilter([
+ Filter.whereField("a", in: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
+ Filter.whereField("b", in: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ ]))
+ // [END 20_disjunctions]
+
+ // [START 10_disjunctions]
+ collection.whereFilter(Filter.andFilter([
+ Filter.whereField("a", in: [1, 2, 3, 4, 5]),
+ Filter.orFilter([
+ Filter.whereField("b", isEqualTo: 2),
+ Filter.whereField("c", isEqualTo: 3)
+ ])
+ ]))
+ // [END 10_disjunctions]
+ }
+
+ // This method crashes, so don't include it in the smoketest.
+ func illegalDisjunctions() {
+ let collection = db.collection("cities")
+
+ // [START 50_disjunctions]
+ collection.whereFilter(Filter.andFilter([
+ Filter.whereField("a", in: [1, 2, 3, 4, 5]),
+ Filter.whereField("b", in: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ ]))
+ // [END 50_disjunctions]
+ }
- private func emulatorSettings() {
- // [START fs_emulator_connect]
- let settings = Firestore.firestore().settings
- settings.host = "localhost:8080"
- settings.isPersistenceEnabled = false
- settings.isSSLEnabled = false
- Firestore.firestore().settings = settings
- // [END fs_emulator_connect]
- }
}
-fileprivate struct City {
+// [START codable_struct]
+public struct City: Codable, Sendable {
- let name: String
- let state: String?
- let country: String?
- let capital: Bool?
- let population: Int64?
+ let name: String
+ let state: String?
+ let country: String?
+ let isCapital: Bool?
+ let population: Int64?
- init?(dictionary: [String: Any]) {
- guard let name = dictionary["name"] as? String else { return nil }
- self.name = name
-
- self.state = dictionary["state"] as? String
- self.country = dictionary["country"] as? String
- self.capital = dictionary["capital"] as? Bool
- self.population = dictionary["population"] as? Int64
- }
+ enum CodingKeys: String, CodingKey {
+ case name
+ case state
+ case country
+ case isCapital = "capital"
+ case population
+ }
}
-
+// [END codable_struct]
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.pbxproj b/firoptions/FiroptionConfiguration.xcodeproj/project.pbxproj
similarity index 68%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.pbxproj
rename to firoptions/FiroptionConfiguration.xcodeproj/project.pbxproj
index 2500f165..6c7323c0 100644
--- a/firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.pbxproj
+++ b/firoptions/FiroptionConfiguration.xcodeproj/project.pbxproj
@@ -3,10 +3,19 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
+ 8D7951AC2D28AF88000FD694 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951AB2D28AF88000FD694 /* FirebaseAnalytics */; };
+ 8D7951AE2D28AF88000FD694 /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951AD2D28AF88000FD694 /* FirebaseCore */; };
+ 8D7951B02D28AF88000FD694 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951AF2D28AF88000FD694 /* FirebaseDatabase */; };
+ 8D7951B22D28AFF4000FD694 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951B12D28AFF4000FD694 /* FirebaseAnalytics */; };
+ 8D7951B42D28AFF4000FD694 /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951B32D28AFF4000FD694 /* FirebaseCore */; };
+ 8D7951B62D28B003000FD694 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951B52D28B003000FD694 /* FirebaseDatabase */; };
+ 8DFC20162410844B004392AD /* AnalyticsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DFC20152410844B004392AD /* AnalyticsHelper.m */; };
+ A19F764427EDED14002DE108 /* ISImpressionData.m in Sources */ = {isa = PBXBuildFile; fileRef = A19F764027EDED14002DE108 /* ISImpressionData.m */; };
+ A19F764527EDED14002DE108 /* MAAd.m in Sources */ = {isa = PBXBuildFile; fileRef = A19F764327EDED14002DE108 /* MAAd.m */; };
EFEC9D631E01BF310021BDF9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFEC9D621E01BF310021BDF9 /* AppDelegate.swift */; };
EFEC9D651E01BF310021BDF9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFEC9D641E01BF310021BDF9 /* ViewController.swift */; };
EFEC9D681E01BF310021BDF9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EFEC9D661E01BF310021BDF9 /* Main.storyboard */; };
@@ -23,6 +32,13 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 8DFC20132410844A004392AD /* FiroptionConfiguration-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FiroptionConfiguration-Bridging-Header.h"; sourceTree = ""; };
+ 8DFC20142410844B004392AD /* AnalyticsHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnalyticsHelper.h; sourceTree = ""; };
+ 8DFC20152410844B004392AD /* AnalyticsHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AnalyticsHelper.m; sourceTree = ""; };
+ A19F764027EDED14002DE108 /* ISImpressionData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ISImpressionData.m; sourceTree = ""; };
+ A19F764127EDED14002DE108 /* ISImpressionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISImpressionData.h; sourceTree = ""; };
+ A19F764227EDED14002DE108 /* MAAd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MAAd.h; sourceTree = ""; };
+ A19F764327EDED14002DE108 /* MAAd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MAAd.m; sourceTree = ""; };
EFEC9D5F1E01BF310021BDF9 /* FiroptionConfiguration.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FiroptionConfiguration.app; sourceTree = BUILT_PRODUCTS_DIR; };
EFEC9D621E01BF310021BDF9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
EFEC9D641E01BF310021BDF9 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
@@ -41,6 +57,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D7951B02D28AF88000FD694 /* FirebaseDatabase in Frameworks */,
+ 8D7951AE2D28AF88000FD694 /* FirebaseCore in Frameworks */,
+ 8D7951AC2D28AF88000FD694 /* FirebaseAnalytics in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -48,17 +67,28 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D7951B62D28B003000FD694 /* FirebaseDatabase in Frameworks */,
+ 8D7951B42D28AFF4000FD694 /* FirebaseCore in Frameworks */,
+ 8D7951B22D28AFF4000FD694 /* FirebaseAnalytics in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 8D7951AA2D28AF88000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
EFEC9D561E01BF310021BDF9 = {
isa = PBXGroup;
children = (
EFEC9D9B1E01EEB60021BDF9 /* Dev */,
EFEC9D611E01BF310021BDF9 /* FiroptionConfiguration */,
+ 8D7951AA2D28AF88000FD694 /* Frameworks */,
EFEC9D601E01BF310021BDF9 /* Products */,
);
sourceTree = "";
@@ -79,10 +109,17 @@
EFEC9D951E01EE9F0021BDF9 /* MyGoogleService.plist */,
EFEC9D621E01BF310021BDF9 /* AppDelegate.swift */,
EFEC9D641E01BF310021BDF9 /* ViewController.swift */,
+ 8DFC20142410844B004392AD /* AnalyticsHelper.h */,
+ 8DFC20152410844B004392AD /* AnalyticsHelper.m */,
+ A19F764127EDED14002DE108 /* ISImpressionData.h */,
+ A19F764027EDED14002DE108 /* ISImpressionData.m */,
+ A19F764227EDED14002DE108 /* MAAd.h */,
+ A19F764327EDED14002DE108 /* MAAd.m */,
EFEC9D661E01BF310021BDF9 /* Main.storyboard */,
EFEC9D691E01BF310021BDF9 /* Assets.xcassets */,
EFEC9D6B1E01BF310021BDF9 /* LaunchScreen.storyboard */,
EFEC9D6E1E01BF310021BDF9 /* Info.plist */,
+ 8DFC20132410844A004392AD /* FiroptionConfiguration-Bridging-Header.h */,
);
path = FiroptionConfiguration;
sourceTree = "";
@@ -138,13 +175,15 @@
EFEC9D571E01BF310021BDF9 /* Project object */ = {
isa = PBXProject;
attributes = {
+ BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0820;
- LastUpgradeCheck = 0820;
+ LastUpgradeCheck = 1610;
ORGANIZATIONNAME = Google;
TargetAttributes = {
EFEC9D5E1E01BF310021BDF9 = {
CreatedOnToolsVersion = 8.2;
DevelopmentTeam = EQHXZ8M8AV;
+ LastSwiftMigration = 1130;
ProvisioningStyle = Automatic;
};
EFEC9D771E01C6560021BDF9 = {
@@ -156,13 +195,16 @@
};
buildConfigurationList = EFEC9D5A1E01BF310021BDF9 /* Build configuration list for PBXProject "FiroptionConfiguration" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = EFEC9D561E01BF310021BDF9;
+ packageReferences = (
+ 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
productRefGroup = EFEC9D601E01BF310021BDF9 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -204,8 +246,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A19F764527EDED14002DE108 /* MAAd.m in Sources */,
+ A19F764427EDED14002DE108 /* ISImpressionData.m in Sources */,
EFEC9D651E01BF310021BDF9 /* ViewController.swift in Sources */,
EFEC9D631E01BF310021BDF9 /* AppDelegate.swift in Sources */,
+ 8DFC20162410844B004392AD /* AnalyticsHelper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -249,15 +294,24 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -266,6 +320,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -280,7 +335,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -299,15 +354,24 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -316,6 +380,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -324,10 +389,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -337,12 +403,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = EQHXZ8M8AV;
INFOPLIST_FILE = FiroptionConfiguration/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.devrel.FiroptionConfiguration;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_OBJC_BRIDGING_HEADER = "FiroptionConfiguration/FiroptionConfiguration-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -350,12 +422,17 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = EQHXZ8M8AV;
INFOPLIST_FILE = FiroptionConfiguration/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.devrel.FiroptionConfiguration;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_OBJC_BRIDGING_HEADER = "FiroptionConfiguration/FiroptionConfiguration-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -365,10 +442,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = EQHXZ8M8AV;
INFOPLIST_FILE = "$(SRCROOT)/FiroptionConfiguration/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.devrel.FiroptionConfigurationDev;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -378,10 +458,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = EQHXZ8M8AV;
INFOPLIST_FILE = "$(SRCROOT)/FiroptionConfiguration/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.devrel.FiroptionConfigurationDev;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -416,6 +499,50 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7951AB2D28AF88000FD694 /* FirebaseAnalytics */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAnalytics;
+ };
+ 8D7951AD2D28AF88000FD694 /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+ 8D7951AF2D28AF88000FD694 /* FirebaseDatabase */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseDatabase;
+ };
+ 8D7951B12D28AFF4000FD694 /* FirebaseAnalytics */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseAnalytics;
+ };
+ 8D7951B32D28AFF4000FD694 /* FirebaseCore */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseCore;
+ };
+ 8D7951B52D28B003000FD694 /* FirebaseDatabase */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951A92D28AF6D000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseDatabase;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = EFEC9D571E01BF310021BDF9 /* Project object */;
}
diff --git a/firoptions/FiroptionConfiguration/AnalyticsHelper.h b/firoptions/FiroptionConfiguration/AnalyticsHelper.h
new file mode 100644
index 00000000..dd2ec27e
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/AnalyticsHelper.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AnalyticsHelper: NSObject
+
+@end
+NS_ASSUME_NONNULL_END
diff --git a/firoptions/FiroptionConfiguration/AnalyticsHelper.m b/firoptions/FiroptionConfiguration/AnalyticsHelper.m
new file mode 100644
index 00000000..4e60417c
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/AnalyticsHelper.m
@@ -0,0 +1,326 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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 FirebaseAnalytics;
+
+#import "AnalyticsHelper.h"
+
+// Importing simulated 3rd party ad_impressions to ensure this project compiles. Not required to implement Firebase ad_impression tracking
+#import "MAAd.h"
+#import "ISImpressionData.h"
+
+@implementation AnalyticsHelper
+
+- (void)logInAppPurchase {
+ // [START ecommerce_purchase]
+ [FIRAnalytics logEventWithName:kFIREventPurchase
+ parameters:@{
+ kFIRParameterCoupon: @"SummerPromo",
+ kFIRParameterCurrency: @"JPY",
+ kFIRParameterValue: @10000,
+ kFIRParameterShipping: @500,
+ kFIRParameterTransactionID: @"192803301",
+ }];
+ // [END ecommerce_purchase]
+}
+
+- (void)enhancedEcommerce {
+ // Implementation
+
+ // [START create_items]
+ // A pair of jeggings
+ NSMutableDictionary *jeggings = [@{
+ kFIRParameterItemID: @"SKU_123",
+ kFIRParameterItemName: @"jeggings",
+ kFIRParameterItemCategory: @"pants",
+ kFIRParameterItemVariant: @"black",
+ kFIRParameterItemBrand: @"Google",
+ kFIRParameterPrice: @9.99,
+ } mutableCopy];
+
+ // A pair of boots
+ NSMutableDictionary *boots = [@{
+ kFIRParameterItemID: @"SKU_456",
+ kFIRParameterItemName: @"boots",
+ kFIRParameterItemCategory: @"shoes",
+ kFIRParameterItemVariant: @"brown",
+ kFIRParameterItemBrand: @"Google",
+ kFIRParameterPrice: @24.99,
+ } mutableCopy];
+
+ // A pair of socks
+ NSMutableDictionary *socks = [@{
+ kFIRParameterItemID: @"SKU_789",
+ kFIRParameterItemName: @"ankle_socks",
+ kFIRParameterItemCategory: @"socks",
+ kFIRParameterItemVariant: @"red",
+ kFIRParameterItemBrand: @"Google",
+ kFIRParameterPrice: @5.99,
+ } mutableCopy];
+ // [END create_items]
+
+ // Selecting a product from a list
+
+ // [START view_item_list]
+ // Add item indexes
+ jeggings[kFIRParameterIndex] = @1;
+ boots[kFIRParameterIndex] = @2;
+ socks[kFIRParameterIndex] = @3;
+
+ // Prepare ecommerce parameters
+ NSMutableDictionary *itemList = [@{
+ kFIRParameterItemListID: @"L001",
+ kFIRParameterItemListName: @"Related products",
+ } mutableCopy];
+
+ // Add items array
+ itemList[kFIRParameterItems] = @[jeggings, boots, socks];
+
+ // Log view item list event
+ [FIRAnalytics logEventWithName:kFIREventViewItemList parameters:itemList];
+ // [END view_item_list]
+
+ // [START select_item]
+ // Prepare ecommerce parameters
+ NSMutableDictionary *selectedItem = [@{
+ kFIRParameterItemListID: @"L001",
+ kFIRParameterItemListName: @"Related products",
+ } mutableCopy];
+
+ // Add items array
+ selectedItem[kFIRParameterItems] = @[jeggings];
+
+ // Log select item event
+ [FIRAnalytics logEventWithName:kFIREventSelectItem parameters:selectedItem];
+ // [END select_item]
+
+ // Viewing product details
+
+ // [START view_product_details]
+ // Prepare ecommerce parameters
+ NSMutableDictionary *productDetails = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @9.99
+ } mutableCopy];
+
+ // Add items array
+ productDetails[kFIRParameterItems] = @[jeggings];
+
+ // Log view item event
+ [FIRAnalytics logEventWithName:kFIREventViewItem parameters:productDetails];
+ // [END view_product_details]
+
+ // Adding/Removing a product from shopping cart
+
+ // [START add_to_cart_wishlist]
+ // Specify order quantity
+ jeggings[kFIRParameterQuantity] = @2;
+
+ // Prepare item detail params
+ NSMutableDictionary *itemDetails = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @19.98
+ } mutableCopy];
+
+ // Add items
+ itemDetails[kFIRParameterItems] = @[jeggings];
+
+ // Log an event when product is added to wishlist
+ [FIRAnalytics logEventWithName:kFIREventAddToWishlist parameters:itemDetails];
+
+ // Log an event when product is added to cart
+ [FIRAnalytics logEventWithName:kFIREventAddToCart parameters:itemDetails];
+ // [END add_to_cart_wishlist]
+
+ // [START view_cart]
+ // Specify order quantity
+ jeggings[kFIRParameterQuantity] = @2;
+ boots[kFIRParameterQuantity] = @1;
+
+ // Prepare order parameters
+ NSMutableDictionary *orderParameters = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @44.97
+ } mutableCopy];
+
+ // Add items array
+ orderParameters[kFIRParameterItems] = @[jeggings, boots];
+
+ // Log event when cart is viewed
+ [FIRAnalytics logEventWithName:kFIREventViewCart parameters:orderParameters];
+ // [END view_cart]
+
+ // [START remove_from_cart]
+ // Specify removal quantity
+ boots[kFIRParameterQuantity] = @1;
+
+ // Prepare params
+ NSMutableDictionary *removeParams = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @24.99
+ } mutableCopy];
+
+ // Add items
+ removeParams[kFIRParameterItems] = @[boots];
+
+ // Log removal event
+ [FIRAnalytics logEventWithName:kFIREventRemoveFromCart parameters:removeParams];
+ // [END remove_from_cart]
+
+ // Initiating the checkout process
+
+ // [START start_checkout]
+ // Prepare checkout params
+ NSMutableDictionary *checkoutParams = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @14.98,
+ kFIRParameterCoupon: @"SUMMER_FUN"
+ } mutableCopy];
+
+ // Add items
+ checkoutParams[kFIRParameterItems] = @[jeggings];
+
+ // Log checkout event
+ [FIRAnalytics logEventWithName:kFIREventBeginCheckout parameters:checkoutParams];
+ // [END start_checkout]
+
+ // [START add_shipping]
+ // Prepare shipping params
+ NSMutableDictionary *shippingParams = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @14.98,
+ kFIRParameterCoupon: @"SUMMER_FUN",
+ kFIRParameterShippingTier: @"Ground"
+ } mutableCopy];
+
+ // Add items
+ shippingParams[kFIRParameterItems] = @[jeggings];
+
+ // Log added shipping info event
+ [FIRAnalytics logEventWithName:kFIREventAddShippingInfo parameters:shippingParams];
+ // [END add_shipping]
+
+ // [START add_payment]
+ // Prepare payment params
+ NSMutableDictionary *paymentParams = [@{
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @14.98,
+ kFIRParameterCoupon: @"SUMMER_FUN",
+ kFIRParameterPaymentType: @"Visa"
+ } mutableCopy];
+
+ // Add items
+ paymentParams[kFIRParameterItems] = @[jeggings];
+
+ // Log added payment info event
+ [FIRAnalytics logEventWithName:kFIREventAddPaymentInfo parameters:paymentParams];
+ // [END add_payment]
+
+ // Making a purchase or issuing a refund
+
+ // [START log_purchase]
+ // Prepare purchase params
+ NSMutableDictionary *purchaseParams = [@{
+ kFIRParameterTransactionID: @"T12345",
+ kFIRParameterAffiliation: @"Google Store",
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @14.98,
+ kFIRParameterTax: @2.58,
+ kFIRParameterShipping: @5.34,
+ kFIRParameterCoupon: @"SUMMER_FUN"
+ } mutableCopy];
+
+ // Add items
+ purchaseParams[kFIRParameterItems] = @[jeggings];
+
+ // Log purchase event
+ [FIRAnalytics logEventWithName:kFIREventPurchase parameters:purchaseParams];
+ // [END log_purchase]
+
+ // [START log_refund]
+ // Prepare refund params
+ NSMutableDictionary *refundParams = [@{
+ kFIRParameterTransactionID: @"T12345",
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: @9.99,
+ } mutableCopy];
+
+ // (Optional) for partial refunds, define the item ID and quantity of refunded items
+ NSDictionary *refundedProduct = @{
+ kFIRParameterItemID: @"SKU_123",
+ kFIRParameterQuantity: @1,
+ };
+
+ // Add items
+ refundParams[kFIRParameterItems] = @[refundedProduct];
+
+ // Log refund event
+ [FIRAnalytics logEventWithName:kFIREventRefund parameters:refundParams];
+ // [END log_refund]
+
+ // Applying promotions
+
+ // [START apply_promo]
+ // Prepare promotion parameters
+ NSMutableDictionary *promoParams = [@{
+ kFIRParameterPromotionID: @"T12345",
+ kFIRParameterPromotionName: @"Summer Sale",
+ kFIRParameterCreativeName: @"summer2020_promo.jpg",
+ kFIRParameterCreativeSlot: @"featured_app_1",
+ kFIRParameterLocationID: @"HERO_BANNER",
+ } mutableCopy];
+
+ // Add items
+ promoParams[kFIRParameterItems] = @[jeggings];
+
+ // Log event when promotion is displayed
+ [FIRAnalytics logEventWithName:kFIREventViewPromotion parameters:promoParams];
+
+ // Log event when promotion is selected
+ [FIRAnalytics logEventWithName:kFIREventSelectPromotion parameters:promoParams];
+ // [END apply_promo]
+}
+
+// MARK: ad_impression
+// Log ad_impression for sharing advertising impression data.
+// [START log_ad_impression_applovin]
+- (void)didPayRevenueForAd:(MAAd *)impressionData {
+ [FIRAnalytics logEventWithName:kFIREventAdImpression
+ parameters: @{
+ kFIRParameterAdPlatform: @"AppLovin",
+ kFIRParameterAdSource: impressionData.networkName,
+ kFIRParameterAdFormat: impressionData.format,
+ kFIRParameterAdUnitName: impressionData.adUnitIdentifier,
+ kFIRParameterCurrency: @"USD", // All Applovin revenue is sent in USD
+ kFIRParameterValue: impressionData.revenue
+ }];
+}
+// [END log_ad_impression_applovin]
+
+// [START log_ad_impression_ironsource]
+- (void)impressionDataDidSucceed:(ISImpressionData *)impressionData {
+ [FIRAnalytics logEventWithName:kFIREventAdImpression
+ parameters:@{
+ kFIRParameterAdPlatform: @"ironSource",
+ kFIRParameterAdSource: impressionData.ad_network,
+ kFIRParameterAdFormat: impressionData.ad_unit,
+ kFIRParameterAdUnitName: impressionData.instance_name,
+ kFIRParameterCurrency: @"USD",
+ kFIRParameterValue: impressionData.revenue
+ }];
+}
+// [END log_ad_impression_ironsource]
+@end
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/AppDelegate.swift b/firoptions/FiroptionConfiguration/AppDelegate.swift
similarity index 70%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/AppDelegate.swift
rename to firoptions/FiroptionConfiguration/AppDelegate.swift
index 30dd8ae0..9fad7a29 100644
--- a/firoptions/FiroptionConfiguration/FiroptionConfiguration/AppDelegate.swift
+++ b/firoptions/FiroptionConfiguration/AppDelegate.swift
@@ -15,7 +15,7 @@
//
import UIKit
-import Firebase
+import FirebaseCore
import FirebaseDatabase
@UIApplicationMain
@@ -24,7 +24,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// [START default_configure]
// Use the default GoogleService-Info.plist.
@@ -36,21 +36,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// [START default_configure_file]
// Load a named file.
- let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist")
- guard let fileopts = FirebaseOptions(contentsOfFile: filePath!)
- else { assert(false, "Couldn't load config file") }
- FirebaseApp.configure(options: fileopts)
+ guard
+ let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist"),
+ let fileOptions = FirebaseOptions(contentsOfFile: filePath)
+ else { fatalError("Couldn't load config file.") }
+ FirebaseApp.configure(options: fileOptions)
// [END default_configure_file]
// Note: this one is not deleted, so is the default below.
// [START default_configure_vars]
- // Configure with manual options.
- let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a", gcmSenderID: "27992087142")
- secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
+ // Configure with manual options. Note that projectID and apiKey, though not
+ // required by the initializer, are mandatory.
+ let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a",
+ gcmSenderID: "27992087142")
secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk"
+ secondaryOptions.projectID = "projectid-12345"
+
+ // The other options are not mandatory, but may be required
+ // for specific Firebase products.
+ secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
secondaryOptions.clientID = "27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
secondaryOptions.storageBucket = "myproject.appspot.com"
+ secondaryOptions.deepLinkURLScheme = "myapp://"
+ secondaryOptions.storageBucket = "projectid-12345.appspot.com"
+ secondaryOptions.appGroupID = nil
// [END default_configure_vars]
@@ -60,7 +70,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Retrieve a previous created named app.
guard let secondary = FirebaseApp.app(name: "secondary")
- else { assert(false, "Could not retrieve secondary app") }
+ else { fatalError("Could not retrieve secondary app") }
// Retrieve a Real Time Database client configured against a specific app.
@@ -71,7 +81,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
let defaultDb = Database.database()
guard let defapp = FirebaseApp.app()
- else { assert(false, "Could not retrieve default app") }
+ else { fatalError("Could not retrieve default app") }
assert(secondaryDb.app == secondary)
assert(defaultDb.app == defapp)
@@ -79,6 +89,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return true
}
-
}
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/Assets.xcassets/AppIcon.appiconset/Contents.json b/firoptions/FiroptionConfiguration/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to firoptions/FiroptionConfiguration/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/Base.lproj/LaunchScreen.storyboard b/firoptions/FiroptionConfiguration/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/Base.lproj/LaunchScreen.storyboard
rename to firoptions/FiroptionConfiguration/Base.lproj/LaunchScreen.storyboard
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/Base.lproj/Main.storyboard b/firoptions/FiroptionConfiguration/Base.lproj/Main.storyboard
similarity index 100%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/Base.lproj/Main.storyboard
rename to firoptions/FiroptionConfiguration/Base.lproj/Main.storyboard
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration-Bridging-Header.h b/firoptions/FiroptionConfiguration/FiroptionConfiguration-Bridging-Header.h
new file mode 100644
index 00000000..1b2cb5d6
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/FiroptionConfiguration-Bridging-Header.h
@@ -0,0 +1,4 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index ee044f00..00000000
--- a/firoptions/FiroptionConfiguration/FiroptionConfiguration.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/GoogleService-Info.plist b/firoptions/FiroptionConfiguration/FiroptionConfiguration/GoogleService-Info.plist
deleted file mode 100644
index 7383dabf..00000000
--- a/firoptions/FiroptionConfiguration/FiroptionConfiguration/GoogleService-Info.plist
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
- AD_UNIT_ID_FOR_BANNER_TEST
- ca-app-pub-3940256099942544/2934735716
- AD_UNIT_ID_FOR_INTERSTITIAL_TEST
- ca-app-pub-3940256099942544/4411468910
- CLIENT_ID
- 27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com
- REVERSED_CLIENT_ID
- com.googleusercontent.apps.27992087142-ola6qe637ulk8780vl8mo5vogegkm23n
- API_KEY
- AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk
- GCM_SENDER_ID
- 27992087142
- PLIST_VERSION
- 1
- BUNDLE_ID
- com.google.firebase.devrel.FiroptionConfiguration
- PROJECT_ID
- referencecodeproject
- STORAGE_BUCKET
- referencecodeproject.appspot.com
- IS_ADS_ENABLED
-
- IS_ANALYTICS_ENABLED
-
- IS_APPINVITE_ENABLED
-
- IS_GCM_ENABLED
-
- IS_SIGNIN_ENABLED
-
- GOOGLE_APP_ID
- 1:27992087142:ios:2a4732a34787067a
- DATABASE_URL
- https://referencecodeproject.firebaseio.com
-
-
\ No newline at end of file
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfigurationDev/GoogleService-Info.plist b/firoptions/FiroptionConfiguration/FiroptionConfigurationDev/GoogleService-Info.plist
deleted file mode 100644
index 369b7275..00000000
--- a/firoptions/FiroptionConfiguration/FiroptionConfigurationDev/GoogleService-Info.plist
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
- AD_UNIT_ID_FOR_BANNER_TEST
- ca-app-pub-3940256099942544/2934735716
- AD_UNIT_ID_FOR_INTERSTITIAL_TEST
- ca-app-pub-3940256099942544/4411468910
- CLIENT_ID
- 27992087142-s70q70uud698s86nae5iml0ildcvck9d.apps.googleusercontent.com
- REVERSED_CLIENT_ID
- com.googleusercontent.apps.27992087142-s70q70uud698s86nae5iml0ildcvck9d
- API_KEY
- AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk
- GCM_SENDER_ID
- 27992087142
- PLIST_VERSION
- 1
- BUNDLE_ID
- com.google.firebase.devrel.FiroptionConfigurationDev
- PROJECT_ID
- referencecodeproject
- STORAGE_BUCKET
- referencecodeproject.appspot.com
- IS_ADS_ENABLED
-
- IS_ANALYTICS_ENABLED
-
- IS_APPINVITE_ENABLED
-
- IS_GCM_ENABLED
-
- IS_SIGNIN_ENABLED
-
- GOOGLE_APP_ID
- 1:27992087142:ios:db637d668463ee8e
- DATABASE_URL
- https://referencecodeproject.firebaseio.com
-
-
\ No newline at end of file
diff --git a/firoptions/FiroptionConfiguration/ISImpressionData.h b/firoptions/FiroptionConfiguration/ISImpressionData.h
new file mode 100644
index 00000000..24e159f9
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/ISImpressionData.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+
+@interface ISImpressionData: NSObject
+// Simulated ad_impression structures from mediation platforms to ensure that this project compiles.
+// Ironsource Sample Publisher Ad Impression
+@property (nonatomic, strong) NSString *ad_network;
+@property (nonatomic, strong) NSString *ad_unit;
+@property (nonatomic, strong) NSString *instance_name;
+@property (nonatomic) NSNumber *revenue;
+
+@end
diff --git a/firoptions/FiroptionConfiguration/ISImpressionData.m b/firoptions/FiroptionConfiguration/ISImpressionData.m
new file mode 100644
index 00000000..85d13c01
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/ISImpressionData.m
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+#import "ISImpressionData.h"
+// Simulated ad_impression structures from mediation platforms to ensure that this project compiles
+// Ironsource Sample Publisher Ad Impression
+@implementation ISImpressionData
+
+@end
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/Info.plist b/firoptions/FiroptionConfiguration/Info.plist
similarity index 100%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/Info.plist
rename to firoptions/FiroptionConfiguration/Info.plist
diff --git a/firoptions/FiroptionConfiguration/MAAd.h b/firoptions/FiroptionConfiguration/MAAd.h
new file mode 100644
index 00000000..b39f5cbc
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/MAAd.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+
+@interface MAAd:NSObject
+// Simulated ad_impression structures from mediation platforms to ensure that this project compiles
+// AppLovin Sample Publisher Ad Impression
+@property (nonatomic, strong) NSString *adUnitIdentifier;
+@property (nonatomic, strong) NSString *networkName;
+@property (nonatomic, strong) NSString *format;
+@property (nonatomic) NSNumber *revenue;
+
+@end
diff --git a/firoptions/FiroptionConfiguration/MAAd.m b/firoptions/FiroptionConfiguration/MAAd.m
new file mode 100644
index 00000000..3b441d19
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/MAAd.m
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+#import "MAAd.h"
+// Simulated ad_impression structures from mediation platforms to ensure that this project compiles
+@implementation MAAd
+
+@end
diff --git a/firoptions/FiroptionConfiguration/FiroptionConfiguration/MyGoogleService.plist b/firoptions/FiroptionConfiguration/MyGoogleService.plist
similarity index 100%
rename from firoptions/FiroptionConfiguration/FiroptionConfiguration/MyGoogleService.plist
rename to firoptions/FiroptionConfiguration/MyGoogleService.plist
diff --git a/firoptions/FiroptionConfiguration/Podfile b/firoptions/FiroptionConfiguration/Podfile
deleted file mode 100644
index 99971c5b..00000000
--- a/firoptions/FiroptionConfiguration/Podfile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Uncomment the next line to define a global platform for your project
-# platform :ios, '9.0'
-
-target 'FiroptionConfiguration' do
- # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
- use_frameworks!
-
- # Pods for FiroptionConfiguration
- pod 'Firebase/Core'
- pod 'Firebase/Database'
-
-end
diff --git a/firoptions/FiroptionConfiguration/Podfile.lock b/firoptions/FiroptionConfiguration/Podfile.lock
deleted file mode 100644
index bf75f472..00000000
--- a/firoptions/FiroptionConfiguration/Podfile.lock
+++ /dev/null
@@ -1,113 +0,0 @@
-PODS:
- - Firebase/Core (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAnalytics (= 6.1.1)
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/Database (6.8.0):
- - Firebase/CoreOnly
- - FirebaseDatabase (~> 6.1.0)
- - FirebaseAnalytics (6.1.1):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
- - GoogleAppMeasurement (= 6.1.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - FirebaseAuthInterop (1.0.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseDatabase (6.1.0):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.0)
- - leveldb-library (~> 1.18)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - GoogleAppMeasurement (6.1.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/AppDelegateSwizzler (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (6.2.5):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.2.5)"
- - GoogleUtilities/Reachability (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.2.5):
- - GoogleUtilities/Logger
- - leveldb-library (1.22)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
-
-DEPENDENCIES:
- - Firebase/Core
- - Firebase/Database
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - Firebase
- - FirebaseAnalytics
- - FirebaseAuthInterop
- - FirebaseCore
- - FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseDatabase
- - FirebaseInstanceID
- - GoogleAppMeasurement
- - GoogleDataTransport
- - GoogleDataTransportCCTSupport
- - GoogleUtilities
- - leveldb-library
- - nanopb
-
-SPEC CHECKSUMS:
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
- FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseDatabase: 518cd94286de2ee999e19383a2a6ae04c81ce993
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
-
-PODFILE CHECKSUM: a19f89b9a2d7ad92954885375c3e7dcafa52d969
-
-COCOAPODS: 1.7.5
diff --git a/firoptions/FiroptionConfiguration/ViewController.swift b/firoptions/FiroptionConfiguration/ViewController.swift
new file mode 100644
index 00000000..b8eeab6d
--- /dev/null
+++ b/firoptions/FiroptionConfiguration/ViewController.swift
@@ -0,0 +1,376 @@
+//
+// Copyright (c) 2017 Google Inc.
+//
+// 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 FirebaseAnalytics
+
+class ViewController: UIViewController {
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ }
+
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+ func logInAppPurchaseEvent() {
+ // [START ecommerce_purchase]
+ Analytics.logEvent(AnalyticsEventPurchase, parameters: [
+ AnalyticsParameterCoupon: "SummerPromo",
+ AnalyticsParameterCurrency: "JPY",
+ AnalyticsParameterValue: 10000,
+ AnalyticsParameterShipping: 500,
+ AnalyticsParameterTransactionID: "192803301",
+ ])
+ // [END ecommerce_purchase]
+ }
+
+ func enhancedEcommerce() {
+ // Implementation
+
+ // [START create_items]
+ // A pair of jeggings
+ var jeggings: [String: Any] = [
+ AnalyticsParameterItemID: "SKU_123",
+ AnalyticsParameterItemName: "jeggings",
+ AnalyticsParameterItemCategory: "pants",
+ AnalyticsParameterItemVariant: "black",
+ AnalyticsParameterItemBrand: "Google",
+ AnalyticsParameterPrice: 9.99,
+ ]
+
+ // A pair of boots
+ var boots: [String: Any] = [
+ AnalyticsParameterItemID: "SKU_456",
+ AnalyticsParameterItemName: "boots",
+ AnalyticsParameterItemCategory: "shoes",
+ AnalyticsParameterItemVariant: "brown",
+ AnalyticsParameterItemBrand: "Google",
+ AnalyticsParameterPrice: 24.99,
+ ]
+
+ // A pair of socks
+ var socks: [String: Any] = [
+ AnalyticsParameterItemID: "SKU_789",
+ AnalyticsParameterItemName: "ankle_socks",
+ AnalyticsParameterItemCategory: "socks",
+ AnalyticsParameterItemVariant: "red",
+ AnalyticsParameterItemBrand: "Google",
+ AnalyticsParameterPrice: 5.99,
+ ]
+ // [END create_items]
+
+ // Selecting a product from a list
+
+ // [START view_item_list]
+ // Add item indexes
+ jeggings[AnalyticsParameterIndex] = 1
+ boots[AnalyticsParameterIndex] = 2
+ socks[AnalyticsParameterIndex] = 3
+
+ // Prepare ecommerce parameters
+ var itemList: [String: Any] = [
+ AnalyticsParameterItemListID: "L001",
+ AnalyticsParameterItemListName: "Related products",
+ ]
+
+ // Add items array
+ itemList[AnalyticsParameterItems] = [jeggings, boots, socks]
+
+ // Log view item list event
+ Analytics.logEvent(AnalyticsEventViewItemList, parameters: itemList)
+ // [END view_item_list]
+
+ // [START select_item]
+ // Prepare ecommerce parameters
+ var selectedItem: [String: Any] = [
+ AnalyticsParameterItemListID: "L001",
+ AnalyticsParameterItemListName: "Related products",
+ ]
+
+ // Add items array
+ selectedItem[AnalyticsParameterItems] = [jeggings]
+
+ // Log select item event
+ Analytics.logEvent(AnalyticsEventSelectItem, parameters: selectedItem)
+ // [END select_item]
+
+ // Viewing product details
+
+ // [START view_product_details]
+ // Prepare ecommerce parameters
+ var productDetails: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 9.99
+ ]
+
+ // Add items array
+ productDetails[AnalyticsParameterItems] = [jeggings]
+
+ // Log view item event
+ Analytics.logEvent(AnalyticsEventViewItem, parameters: productDetails)
+ // [END view_product_details]
+
+ // Adding/Removing a product from shopping cart
+
+ // [START add_to_cart_wishlist]
+ // Specify order quantity
+ jeggings[AnalyticsParameterQuantity] = 2
+
+ // Prepare item detail params
+ var itemDetails: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 19.98
+ ]
+
+ // Add items
+ itemDetails[AnalyticsParameterItems] = [jeggings]
+
+ // Log an event when product is added to wishlist
+ Analytics.logEvent(AnalyticsEventAddToWishlist, parameters: itemDetails)
+
+ // Log an event when product is added to cart
+ Analytics.logEvent(AnalyticsEventAddToCart, parameters: itemDetails)
+ // [END add_to_cart_wishlist]
+
+ // [START view_cart]
+ // Specify order quantity
+ jeggings[AnalyticsParameterQuantity] = 2
+ boots[AnalyticsParameterQuantity] = 1
+
+ // Prepare order parameters
+ var orderParameters: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 44.97
+ ]
+
+ // Add items array
+ orderParameters[AnalyticsParameterItems] = [jeggings, boots]
+
+ // Log event when cart is viewed
+ Analytics.logEvent(AnalyticsEventViewCart, parameters: orderParameters)
+ // [END view_cart]
+
+ // [START remove_from_cart]
+ // Specify removal quantity
+ boots[AnalyticsParameterQuantity] = 1
+
+ // Prepare params
+ var removeParams: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 24.99
+ ]
+
+ // Add items
+ removeParams[AnalyticsParameterItems] = [boots]
+
+ // Log removal event
+ Analytics.logEvent(AnalyticsEventRemoveFromCart, parameters: removeParams)
+ // [END remove_from_cart]
+
+ // Initiating the checkout process
+
+ // [START start_checkout]
+ // Prepare checkout params
+ var checkoutParams: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 14.98,
+ AnalyticsParameterCoupon: "SUMMER_FUN"
+ ];
+
+ // Add items
+ checkoutParams[AnalyticsParameterItems] = [jeggings]
+
+ // Log checkout event
+ Analytics.logEvent(AnalyticsEventBeginCheckout, parameters: checkoutParams)
+ // [END start_checkout]
+
+ // [START add_shipping]
+ // Prepare shipping params
+ var shippingParams: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 14.98,
+ AnalyticsParameterCoupon: "SUMMER_FUN",
+ AnalyticsParameterShippingTier: "Ground"
+ ]
+
+ // Add items
+ shippingParams[AnalyticsParameterItems] = [jeggings]
+
+ // Log added shipping info event
+ Analytics.logEvent(AnalyticsEventAddShippingInfo, parameters: shippingParams)
+ // [END add_shipping]
+
+ // [START add_payment]
+ // Prepare payment params
+ var paymentParams: [String: Any] = [
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 14.98,
+ AnalyticsParameterCoupon: "SUMMER_FUN",
+ AnalyticsParameterPaymentType: "Visa"
+ ]
+
+ // Add items
+ paymentParams[AnalyticsParameterItems] = [jeggings]
+
+ // Log added payment info event
+ Analytics.logEvent(AnalyticsEventAddPaymentInfo, parameters: paymentParams)
+ // [END add_payment]
+
+ // Making a purchase or issuing a refund
+
+ // [START log_purchase]
+ // Prepare purchase params
+ var purchaseParams: [String: Any] = [
+ AnalyticsParameterTransactionID: "T12345",
+ AnalyticsParameterAffiliation: "Google Store",
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 14.98,
+ AnalyticsParameterTax: 2.58,
+ AnalyticsParameterShipping: 5.34,
+ AnalyticsParameterCoupon: "SUMMER_FUN"
+ ]
+
+ // Add items
+ purchaseParams[AnalyticsParameterItems] = [jeggings]
+
+ // Log purchase event
+ Analytics.logEvent(AnalyticsEventPurchase, parameters: purchaseParams)
+ // [END log_purchase]
+
+ // [START log_refund]
+ // Prepare refund params
+ var refundParams: [String: Any] = [
+ AnalyticsParameterTransactionID: "T12345",
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: 9.99,
+ ]
+
+ // (Optional) for partial refunds, define the item ID and quantity of refunded items
+ let refundedProduct: [String: Any] = [
+ AnalyticsParameterItemID: "SKU_123",
+ AnalyticsParameterQuantity: 1,
+ ];
+
+ // Add items
+ refundParams[AnalyticsParameterItems] = [refundedProduct]
+
+ // Log refund event
+ Analytics.logEvent(AnalyticsEventRefund, parameters: refundParams)
+ // [END log_refund]
+
+ // Applying promotions
+
+ // [START apply_promo]
+ // Prepare promotion parameters
+ var promoParams: [String: Any] = [
+ AnalyticsParameterPromotionID: "T12345",
+ AnalyticsParameterPromotionName:"Summer Sale",
+ AnalyticsParameterCreativeName: "summer2020_promo.jpg",
+ AnalyticsParameterCreativeSlot: "featured_app_1",
+ AnalyticsParameterLocationID: "HERO_BANNER",
+ ]
+
+ // Add items
+ promoParams[AnalyticsParameterItems] = [jeggings]
+
+ // Log event when promotion is displayed
+ Analytics.logEvent(AnalyticsEventViewPromotion, parameters: promoParams)
+
+ // Log event when promotion is selected
+ Analytics.logEvent(AnalyticsEventSelectPromotion, parameters: promoParams)
+ // [END apply_promo]
+ }
+ // MARK: ad_impression
+ // Log ad_impression for sharing advertising impression data.
+ // Simulated ad_impression structures from mediation platforms to ensure that this project compiles
+ // Ironsource Sample Pub Ad Impression
+ struct ISImpressionData {
+ let ad_network: String?
+ let ad_unit: String?
+ let instance_name: String?
+ let revenue: Double?
+ }
+ // MoPub Sample Pub Ad Impression
+ struct MPMoPubAd {}
+ // MoPub Sample Pub Ad Impression Data
+ struct MPImpressionData {
+ let adUnitName: String
+ let adUnitFormat: String
+ let publisherRevenue: Double
+ let currency: String
+ let networkName: String
+ let precision: String
+ }
+ // AppLovin Sample Pub Ad Impression
+ struct MAAd {
+ let adUnitIdentifier: String
+ let format: String
+ let revenue: String
+ let networkName: String
+ }
+ // [START log_ad_impression_mopub]
+ func mopubAd(_ ad: MPMoPubAd, didTrackImpressionWith impressionData: MPImpressionData?) {
+ if let impressionData = impressionData {
+ Analytics.logEvent(
+ AnalyticsEventAdImpression,
+ parameters: [
+ AnalyticsParameterAdPlatform: "MoPub",
+ AnalyticsParameterAdUnitName: impressionData.adUnitName,
+ AnalyticsParameterAdFormat: impressionData.adUnitFormat,
+ AnalyticsParameterValue: impressionData.publisherRevenue,
+ AnalyticsParameterCurrency: impressionData.currency,
+ AnalyticsParameterAdSource: impressionData.networkName,
+ "precision": impressionData.precision,
+ ])
+ }
+ }
+ // [END log_ad_impression_mopub]
+
+ // [START log_ad_impression_ironsource]
+ func impressionDataDidSucceed(_ impressionData: ISImpressionData!) {
+ Analytics.logEvent(
+ AnalyticsEventAdImpression,
+ parameters: [
+ AnalyticsParameterAdPlatform: "ironSource",
+ AnalyticsParameterAdSource: impressionData.ad_network ?? "No ad_network",
+ AnalyticsParameterAdFormat: impressionData.ad_unit ?? "No ad_unit",
+ AnalyticsParameterAdUnitName: impressionData.instance_name ?? "No instance_name",
+ AnalyticsParameterCurrency: "USD",
+ AnalyticsParameterValue: impressionData.revenue ?? 0,
+ ])
+ }
+ // [END log_ad_impression_ironsource]
+
+ // [START log_ad_impression_applovin]
+ func didPayRevenue(_ impressionData: MAAd?) {
+ if let impressionData = impressionData {
+ Analytics.logEvent(
+ AnalyticsEventAdImpression,
+ parameters: [
+ AnalyticsParameterAdPlatform: "AppLovin",
+ AnalyticsParameterAdUnitName: impressionData.adUnitIdentifier,
+ AnalyticsParameterAdFormat: impressionData.format,
+ AnalyticsParameterValue: impressionData.revenue,
+ AnalyticsParameterCurrency: "USD", // All Applovin revenue is sent in USD
+ AnalyticsParameterAdSource: impressionData.networkName,
+ ])
+ }
+ }
+ // [END log_ad_impression_applovin]
+}
diff --git a/functions/FunctionsExample.xcodeproj/project.pbxproj b/functions/FunctionsExample.xcodeproj/project.pbxproj
index 54bcb58e..207b4f35 100644
--- a/functions/FunctionsExample.xcodeproj/project.pbxproj
+++ b/functions/FunctionsExample.xcodeproj/project.pbxproj
@@ -3,10 +3,12 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 50;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
+ 8D7951BA2D28B078000FD694 /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951B92D28B078000FD694 /* FirebaseFunctions */; };
+ 8D7951BC2D28B0C4000FD694 /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951BB2D28B0C4000FD694 /* FirebaseFunctions */; };
8D8FA34322F4CAB100213E06 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34222F4CAB100213E06 /* AppDelegate.m */; };
8D8FA34622F4CAB100213E06 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34522F4CAB100213E06 /* ViewController.m */; };
8D8FA34922F4CAB100213E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34722F4CAB100213E06 /* Main.storyboard */; };
@@ -45,6 +47,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D7951BC2D28B0C4000FD694 /* FirebaseFunctions in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -52,17 +55,26 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8D7951BA2D28B078000FD694 /* FirebaseFunctions in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 8D7951B82D28B078000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
8D8FA33522F4CAB100213E06 = {
isa = PBXGroup;
children = (
8D8FA34022F4CAB100213E06 /* FunctionsExample */,
8D8FA35C22F4CAF700213E06 /* FunctionsExampleSwift */,
+ 8D7951B82D28B078000FD694 /* Frameworks */,
8D8FA33F22F4CAB100213E06 /* Products */,
);
sourceTree = "";
@@ -148,8 +160,9 @@
8D8FA33622F4CAB100213E06 /* Project object */ = {
isa = PBXProject;
attributes = {
+ BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1020;
- LastUpgradeCheck = 1020;
+ LastUpgradeCheck = 1610;
ORGANIZATIONNAME = Firebase;
TargetAttributes = {
8D8FA33D22F4CAB100213E06 = {
@@ -169,6 +182,9 @@
Base,
);
mainGroup = 8D8FA33522F4CAB100213E06;
+ packageReferences = (
+ 8D7951B72D28B070000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
productRefGroup = 8D8FA33F22F4CAB100213E06 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -286,6 +302,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -297,6 +314,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -345,6 +363,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -356,6 +375,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -368,6 +388,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -473,6 +494,30 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951B72D28B070000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7951B92D28B078000FD694 /* FirebaseFunctions */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951B72D28B070000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFunctions;
+ };
+ 8D7951BB2D28B0C4000FD694 /* FirebaseFunctions */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951B72D28B070000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFunctions;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 8D8FA33622F4CAB100213E06 /* Project object */;
}
diff --git a/functions/FunctionsExample/AppDelegate.m b/functions/FunctionsExample/AppDelegate.m
index ccf63ce3..69381fe8 100644
--- a/functions/FunctionsExample/AppDelegate.m
+++ b/functions/FunctionsExample/AppDelegate.m
@@ -14,7 +14,7 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseCore;
#import "AppDelegate.h"
diff --git a/functions/FunctionsExample/ViewController.m b/functions/FunctionsExample/ViewController.m
index 5225905a..43c0b699 100644
--- a/functions/FunctionsExample/ViewController.m
+++ b/functions/FunctionsExample/ViewController.m
@@ -14,7 +14,7 @@
// limitations under the License.
//
-@import Firebase;
+@import FirebaseFunctions;
#import "ViewController.h"
@@ -31,7 +31,7 @@ - (void)viewDidLoad {
- (void)emulatorSettings {
// [START functions_emulator_connect]
- [[FIRFunctions functions] useFunctionsEmulatorOrigin:@"http://localhost:5001"];
+ [[FIRFunctions functions] useEmulatorWithHost:@"localhost" port:5001];
// [END functions_emulator_connect]
}
diff --git a/functions/FunctionsExampleSwift/AppDelegate.swift b/functions/FunctionsExampleSwift/AppDelegate.swift
index 26ad4232..6a384187 100644
--- a/functions/FunctionsExampleSwift/AppDelegate.swift
+++ b/functions/FunctionsExampleSwift/AppDelegate.swift
@@ -15,7 +15,7 @@
//
import UIKit
-import Firebase
+import FirebaseCore
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
diff --git a/functions/FunctionsExampleSwift/ViewController.swift b/functions/FunctionsExampleSwift/ViewController.swift
index 68aeb153..0a0c6c25 100644
--- a/functions/FunctionsExampleSwift/ViewController.swift
+++ b/functions/FunctionsExampleSwift/ViewController.swift
@@ -15,7 +15,7 @@
//
import UIKit
-import Firebase
+import FirebaseFunctions
class ViewController: UIViewController {
@@ -26,7 +26,7 @@ class ViewController: UIViewController {
func emulatorSettings() {
// [START functions_emulator_connect]
- Functions.functions().useFunctionsEmulator(origin: "http://localhost:5001")
+ Functions.functions().useEmulator(withHost: "localhost", port: 5001)
// [END functions_emulator_connect]
}
diff --git a/functions/Podfile b/functions/Podfile
deleted file mode 100644
index 070ed351..00000000
--- a/functions/Podfile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Uncomment the next line to define a global platform for your project
-# platform :ios, '9.0'
-
-target 'FunctionsExample' do
- # Comment the next line if you don't want to use dynamic frameworks
- use_frameworks!
-
- pod 'Firebase/Functions'
-
-end
-
-target 'FunctionsExampleSwift' do
- # Comment the next line if you don't want to use dynamic frameworks
- use_frameworks!
-
- pod 'Firebase/Functions'
-
-end
diff --git a/functions/Podfile.lock b/functions/Podfile.lock
deleted file mode 100644
index a409714c..00000000
--- a/functions/Podfile.lock
+++ /dev/null
@@ -1,69 +0,0 @@
-PODS:
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/Functions (6.8.0):
- - Firebase/CoreOnly
- - FirebaseFunctions (~> 2.5.1)
- - FirebaseAuthInterop (1.0.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseFunctions (2.5.1):
- - FirebaseAuthInterop (~> 1.0)
- - FirebaseCore (~> 6.0)
- - GTMSessionFetcher/Core (~> 1.1)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
- - GoogleUtilities/Environment
- - GTMSessionFetcher/Core (1.2.2)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
-
-DEPENDENCIES:
- - Firebase/Functions
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - Firebase
- - FirebaseAuthInterop
- - FirebaseCore
- - FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseFunctions
- - GoogleDataTransport
- - GoogleDataTransportCCTSupport
- - GoogleUtilities
- - GTMSessionFetcher
- - nanopb
-
-SPEC CHECKSUMS:
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseFunctions: 5af7c35d1c5e41608fecbb667eb6c4e672e318d0
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
-
-PODFILE CHECKSUM: 0bf21181414ed35c7e5fc96da7dd0f72b77e7b34
-
-COCOAPODS: 1.7.5
diff --git a/inappmessaging/FIAMReference/FIAMReference.xcodeproj/project.pbxproj b/inappmessaging/FIAMReference/FIAMReference.xcodeproj/project.pbxproj
index 7d111c20..0003f2ea 100644
--- a/inappmessaging/FIAMReference/FIAMReference.xcodeproj/project.pbxproj
+++ b/inappmessaging/FIAMReference/FIAMReference.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 50;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -20,12 +20,11 @@
3E64A7C32294513E003EE93A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3E64A7C12294513E003EE93A /* LaunchScreen.storyboard */; };
3E64A7C9229456A3003EE93A /* CardActionFiamDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E64A7C8229456A3003EE93A /* CardActionFiamDelegate.swift */; };
3E64A7D522946983003EE93A /* CardActionFiamDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E64A7D422946983003EE93A /* CardActionFiamDelegate.m */; };
- 7B57A0C81AD819D38114C0DA /* Pods_FIAMReferenceSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5CB090B898D1808D8BFB45E /* Pods_FIAMReferenceSwift.framework */; };
- 9DC7047D28AC0715DA8758B9 /* Pods_FIAMReference.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F31B861CDBF9DB7CD403440 /* Pods_FIAMReference.framework */; };
+ 8D7951C02D2C8885000FD694 /* FirebaseInAppMessaging-Beta in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951BF2D2C8885000FD694 /* FirebaseInAppMessaging-Beta */; };
+ 8D7951C22D2C888E000FD694 /* FirebaseInAppMessaging-Beta in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951C12D2C888E000FD694 /* FirebaseInAppMessaging-Beta */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 0F31B861CDBF9DB7CD403440 /* Pods_FIAMReference.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FIAMReference.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3E64A798229376BB003EE93A /* FIAMReference.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FIAMReference.app; sourceTree = BUILT_PRODUCTS_DIR; };
3E64A79B229376BB003EE93A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
3E64A79C229376BB003EE93A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
@@ -46,11 +45,6 @@
3E64A7C8229456A3003EE93A /* CardActionFiamDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardActionFiamDelegate.swift; sourceTree = ""; };
3E64A7D322946983003EE93A /* CardActionFiamDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardActionFiamDelegate.h; sourceTree = ""; };
3E64A7D422946983003EE93A /* CardActionFiamDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CardActionFiamDelegate.m; sourceTree = ""; };
- 60DA3A39F9552E8B37AD597C /* Pods-FIAMReferenceSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FIAMReferenceSwift.release.xcconfig"; path = "Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift.release.xcconfig"; sourceTree = ""; };
- 8D026225BF1D8381A23B9CDD /* Pods-FIAMReferenceSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FIAMReferenceSwift.debug.xcconfig"; path = "Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift.debug.xcconfig"; sourceTree = ""; };
- 9E2817EDB630021664AEF7F0 /* Pods-FIAMReference.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FIAMReference.release.xcconfig"; path = "Target Support Files/Pods-FIAMReference/Pods-FIAMReference.release.xcconfig"; sourceTree = ""; };
- B20FEECC6333640D763A6374 /* Pods-FIAMReference.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FIAMReference.debug.xcconfig"; path = "Target Support Files/Pods-FIAMReference/Pods-FIAMReference.debug.xcconfig"; sourceTree = ""; };
- F5CB090B898D1808D8BFB45E /* Pods_FIAMReferenceSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FIAMReferenceSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -58,7 +52,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 9DC7047D28AC0715DA8758B9 /* Pods_FIAMReference.framework in Frameworks */,
+ 8D7951C02D2C8885000FD694 /* FirebaseInAppMessaging-Beta in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -66,7 +60,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 7B57A0C81AD819D38114C0DA /* Pods_FIAMReferenceSwift.framework in Frameworks */,
+ 8D7951C22D2C888E000FD694 /* FirebaseInAppMessaging-Beta in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -79,8 +73,6 @@
3E64A79A229376BB003EE93A /* FIAMReference */,
3E64A7B72294513E003EE93A /* FIAMReferenceSwift */,
3E64A799229376BB003EE93A /* Products */,
- CE6E66E48A82916264FE3F5B /* Pods */,
- A53E5F3D908E32CBF3BBB4EC /* Frameworks */,
);
sourceTree = "";
};
@@ -125,27 +117,6 @@
path = FIAMReferenceSwift;
sourceTree = "";
};
- A53E5F3D908E32CBF3BBB4EC /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- 0F31B861CDBF9DB7CD403440 /* Pods_FIAMReference.framework */,
- F5CB090B898D1808D8BFB45E /* Pods_FIAMReferenceSwift.framework */,
- );
- name = Frameworks;
- sourceTree = "";
- };
- CE6E66E48A82916264FE3F5B /* Pods */ = {
- isa = PBXGroup;
- children = (
- B20FEECC6333640D763A6374 /* Pods-FIAMReference.debug.xcconfig */,
- 9E2817EDB630021664AEF7F0 /* Pods-FIAMReference.release.xcconfig */,
- 8D026225BF1D8381A23B9CDD /* Pods-FIAMReferenceSwift.debug.xcconfig */,
- 60DA3A39F9552E8B37AD597C /* Pods-FIAMReferenceSwift.release.xcconfig */,
- );
- name = Pods;
- path = ../Pods;
- sourceTree = "";
- };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -153,12 +124,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 3E64A7AE229376BC003EE93A /* Build configuration list for PBXNativeTarget "FIAMReference" */;
buildPhases = (
- 46E292585FA315EF59F64499 /* [CP] Check Pods Manifest.lock */,
3E64A794229376BB003EE93A /* Sources */,
3E64A795229376BB003EE93A /* Frameworks */,
3E64A796229376BB003EE93A /* Resources */,
- 65339EA2723DC26D2F6AB3B9 /* [CP] Embed Pods Frameworks */,
- C7965CB691942633E444DB3C /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -173,12 +141,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 3E64A7C72294513E003EE93A /* Build configuration list for PBXNativeTarget "FIAMReferenceSwift" */;
buildPhases = (
- BBF5C5D44E878689104526D9 /* [CP] Check Pods Manifest.lock */,
3E64A7B22294513E003EE93A /* Sources */,
3E64A7B32294513E003EE93A /* Frameworks */,
3E64A7B42294513E003EE93A /* Resources */,
- C45D95F46F4377C48D861896 /* [CP] Embed Pods Frameworks */,
- 771EE35B3102DD3769ED7A38 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -195,8 +160,9 @@
3E64A790229376BB003EE93A /* Project object */ = {
isa = PBXProject;
attributes = {
+ BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1000;
- LastUpgradeCheck = 1000;
+ LastUpgradeCheck = 1610;
ORGANIZATIONNAME = Google;
TargetAttributes = {
3E64A797229376BB003EE93A = {
@@ -216,6 +182,9 @@
Base,
);
mainGroup = 3E64A78F229376BB003EE93A;
+ packageReferences = (
+ 8D7951BD2D2C887B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
productRefGroup = 3E64A799229376BB003EE93A /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -249,121 +218,6 @@
};
/* End PBXResourcesBuildPhase section */
-/* Begin PBXShellScriptBuildPhase section */
- 46E292585FA315EF59F64499 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
- outputFileListPaths = (
- );
- outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-FIAMReference-checkManifestLockResult.txt",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
- showEnvVarsInLog = 0;
- };
- 65339EA2723DC26D2F6AB3B9 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-frameworks-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Embed Pods Frameworks";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-frameworks-${CONFIGURATION}-output-files.xcfilelist",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
- 771EE35B3102DD3769ED7A38 /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-resources-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Copy Pods Resources";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-resources-${CONFIGURATION}-output-files.xcfilelist",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
- BBF5C5D44E878689104526D9 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
- outputFileListPaths = (
- );
- outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-FIAMReferenceSwift-checkManifestLockResult.txt",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
- showEnvVarsInLog = 0;
- };
- C45D95F46F4377C48D861896 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-frameworks-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Embed Pods Frameworks";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-frameworks-${CONFIGURATION}-output-files.xcfilelist",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FIAMReferenceSwift/Pods-FIAMReferenceSwift-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
- C7965CB691942633E444DB3C /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-resources-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Copy Pods Resources";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-resources-${CONFIGURATION}-output-files.xcfilelist",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FIAMReference/Pods-FIAMReference-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
-/* End PBXShellScriptBuildPhase section */
-
/* Begin PBXSourcesBuildPhase section */
3E64A794229376BB003EE93A /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -450,6 +304,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -461,6 +316,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -475,7 +331,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 = 15.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -509,6 +365,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -520,6 +377,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -528,17 +386,17 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
3E64A7AF229376BC003EE93A /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = B20FEECC6333640D763A6374 /* Pods-FIAMReference.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -555,7 +413,6 @@
};
3E64A7B0229376BC003EE93A /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 9E2817EDB630021664AEF7F0 /* Pods-FIAMReference.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -572,7 +429,6 @@
};
3E64A7C52294513E003EE93A /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 8D026225BF1D8381A23B9CDD /* Pods-FIAMReferenceSwift.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -592,7 +448,6 @@
};
3E64A7C62294513E003EE93A /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 60DA3A39F9552E8B37AD597C /* Pods-FIAMReferenceSwift.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
@@ -641,6 +496,30 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951BD2D2C887B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7951BF2D2C8885000FD694 /* FirebaseInAppMessaging-Beta */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951BD2D2C887B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = "FirebaseInAppMessaging-Beta";
+ };
+ 8D7951C12D2C888E000FD694 /* FirebaseInAppMessaging-Beta */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951BD2D2C887B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = "FirebaseInAppMessaging-Beta";
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 3E64A790229376BB003EE93A /* Project object */;
}
diff --git a/inappmessaging/FIAMReference/FIAMReference/AppDelegate.h b/inappmessaging/FIAMReference/FIAMReference/AppDelegate.h
index ec87de4b..a9861fa2 100644
--- a/inappmessaging/FIAMReference/FIAMReference/AppDelegate.h
+++ b/inappmessaging/FIAMReference/FIAMReference/AppDelegate.h
@@ -15,8 +15,6 @@
//
#import
-#import "CardActionFiamDelegate.h"
-@import FirebaseInAppMessaging;
@interface AppDelegate : UIResponder
diff --git a/inappmessaging/FIAMReference/FIAMReference/AppDelegate.m b/inappmessaging/FIAMReference/FIAMReference/AppDelegate.m
index b785ec87..708c1619 100644
--- a/inappmessaging/FIAMReference/FIAMReference/AppDelegate.m
+++ b/inappmessaging/FIAMReference/FIAMReference/AppDelegate.m
@@ -15,7 +15,11 @@
//
#import "AppDelegate.h"
-@import Firebase;
+
+@import FirebaseCore;
+@import FirebaseInAppMessaging;
+
+#import "CardActionFiamDelegate.h"
@interface AppDelegate ()
diff --git a/inappmessaging/FIAMReference/FIAMReference/CardActionFiamDelegate.m b/inappmessaging/FIAMReference/FIAMReference/CardActionFiamDelegate.m
index 929f145d..7d6a0335 100644
--- a/inappmessaging/FIAMReference/FIAMReference/CardActionFiamDelegate.m
+++ b/inappmessaging/FIAMReference/FIAMReference/CardActionFiamDelegate.m
@@ -39,3 +39,20 @@ - (void)messageDismissed:(nonnull FIRInAppMessagingDisplayMessage *)inAppMessage
@end
// [END fiam_card_action_delegate]
+
+@interface ExampleCardActionDelegate: NSObject
+@end
+
+
+// [START fiam_card_action_delegate_bundles]
+@implementation ExampleCardActionDelegate
+
+- (void)messageClicked:(nonnull FIRInAppMessagingDisplayMessage *)inAppMessage {
+ NSDictionary *appData = inAppMessage.appData;
+ NSLog(@"Message data: %@", appData);
+ // ...
+}
+
+@end
+// [END fiam_card_action_delegate_bundles]
+
diff --git a/inappmessaging/FIAMReference/FIAMReferenceSwift/AppDelegate.swift b/inappmessaging/FIAMReference/FIAMReferenceSwift/AppDelegate.swift
index 05d94ae2..f867bf44 100644
--- a/inappmessaging/FIAMReference/FIAMReferenceSwift/AppDelegate.swift
+++ b/inappmessaging/FIAMReference/FIAMReferenceSwift/AppDelegate.swift
@@ -15,7 +15,7 @@
//
import UIKit
-import Firebase
+import FirebaseCore
import FirebaseInAppMessaging
@UIApplicationMain
diff --git a/inappmessaging/FIAMReference/FIAMReferenceSwift/CardActionFiamDelegate.swift b/inappmessaging/FIAMReference/FIAMReferenceSwift/CardActionFiamDelegate.swift
index 0a777bea..6349e9c6 100644
--- a/inappmessaging/FIAMReference/FIAMReferenceSwift/CardActionFiamDelegate.swift
+++ b/inappmessaging/FIAMReference/FIAMReferenceSwift/CardActionFiamDelegate.swift
@@ -14,7 +14,6 @@
// limitations under the License.
//
-import Foundation
import FirebaseInAppMessaging
// [START fiam_card_action_delegate]
@@ -25,7 +24,7 @@ class CardActionFiamDelegate : NSObject, InAppMessagingDisplayDelegate {
}
func messageDismissed(_ inAppMessage: InAppMessagingDisplayMessage,
- dismissType: FIRInAppMessagingDismissType) {
+ dismissType: InAppMessagingDismissType) {
// ...
}
@@ -39,3 +38,15 @@ class CardActionFiamDelegate : NSObject, InAppMessagingDisplayDelegate {
}
// [END fiam_card_action_delegate]
+
+
+// [START fiam_card_action_delegate_bundles]
+class CardActionDelegate : NSObject, InAppMessagingDisplayDelegate {
+
+ func messageClicked(_ inAppMessage: InAppMessagingDisplayMessage) {
+ // Get data bundle from the inapp message
+ let appData = inAppMessage.appData
+ // ...
+ }
+}
+// [END fiam_card_action_delegate_bundles]
diff --git a/inappmessaging/Podfile b/inappmessaging/Podfile
deleted file mode 100644
index 30c17274..00000000
--- a/inappmessaging/Podfile
+++ /dev/null
@@ -1,14 +0,0 @@
-project 'FIAMReference/FIAMReference.xcodeproj/'
-
-platform :ios, '8.0'
-use_frameworks!
-
-pod 'Firebase'
-pod 'Firebase/InAppMessagingDisplay'
-
-target 'FIAMReference' do
-end
-
-target 'FIAMReferenceSwift' do
- use_frameworks!
-end
diff --git a/inappmessaging/Podfile.lock b/inappmessaging/Podfile.lock
deleted file mode 100644
index 19ff0e08..00000000
--- a/inappmessaging/Podfile.lock
+++ /dev/null
@@ -1,118 +0,0 @@
-PODS:
- - Firebase (6.8.0):
- - Firebase/Core (= 6.8.0)
- - Firebase/Core (6.8.0):
- - Firebase/CoreOnly
- - FirebaseAnalytics (= 6.1.1)
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/InAppMessagingDisplay (6.8.0):
- - Firebase/CoreOnly
- - FirebaseInAppMessagingDisplay (~> 0.15.4)
- - FirebaseAnalytics (6.1.1):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
- - GoogleAppMeasurement (= 6.1.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - FirebaseAnalyticsInterop (1.4.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseInAppMessaging (0.15.4):
- - FirebaseAnalyticsInterop (~> 1.3)
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - FirebaseInAppMessagingDisplay (0.15.4):
- - FirebaseCore (~> 6.2)
- - FirebaseInAppMessaging (>= 0.15.0)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - GoogleAppMeasurement (6.1.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- - GoogleUtilities/MethodSwizzler (~> 6.0)
- - GoogleUtilities/Network (~> 6.0)
- - "GoogleUtilities/NSData+zlib (~> 6.0)"
- - nanopb (~> 0.3)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleUtilities/AppDelegateSwizzler (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
- - GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (6.2.5):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (6.2.5)"
- - GoogleUtilities/Reachability (6.2.5):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (6.2.5):
- - GoogleUtilities/Logger
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
-
-DEPENDENCIES:
- - Firebase
- - Firebase/InAppMessagingDisplay
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - Firebase
- - FirebaseAnalytics
- - FirebaseAnalyticsInterop
- - FirebaseCore
- - FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseInAppMessaging
- - FirebaseInAppMessagingDisplay
- - FirebaseInstanceID
- - GoogleAppMeasurement
- - GoogleDataTransport
- - GoogleDataTransportCCTSupport
- - GoogleUtilities
- - nanopb
-
-SPEC CHECKSUMS:
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
- FirebaseAnalyticsInterop: d48b6ab67bcf016a05e55b71fc39c61c0cb6b7f3
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseInAppMessaging: 54bcfe1cf2a48a8f5cdcac487a585c0e9b440d9a
- FirebaseInAppMessagingDisplay: 66267552890939d394a961ee4cac5cdfd41f17bb
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
-
-PODFILE CHECKSUM: ee1d0162c4b114166138141943031a3ae6c42221
-
-COCOAPODS: 1.7.5
diff --git a/installations/InstallationsSnippets.xcodeproj/project.pbxproj b/installations/InstallationsSnippets.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..c66d3adb
--- /dev/null
+++ b/installations/InstallationsSnippets.xcodeproj/project.pbxproj
@@ -0,0 +1,523 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8D7951C62D2C8A15000FD694 /* FirebaseInstallations in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951C52D2C8A15000FD694 /* FirebaseInstallations */; };
+ 8DC74B6624A3DABF004C5F44 /* ObjCSnippets.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DC74B6524A3DABF004C5F44 /* ObjCSnippets.m */; };
+ 8DF2A72824A3D78300737F46 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF2A72724A3D78300737F46 /* AppDelegate.swift */; };
+ 8DF2A72A24A3D78300737F46 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF2A72924A3D78300737F46 /* SceneDelegate.swift */; };
+ 8DF2A72C24A3D78300737F46 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF2A72B24A3D78300737F46 /* ContentView.swift */; };
+ 8DF2A72E24A3D78300737F46 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8DF2A72D24A3D78300737F46 /* Assets.xcassets */; };
+ 8DF2A73124A3D78300737F46 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8DF2A73024A3D78300737F46 /* Preview Assets.xcassets */; };
+ 8DF2A73424A3D78300737F46 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8DF2A73224A3D78300737F46 /* LaunchScreen.storyboard */; };
+ 8DF2A73F24A3D78300737F46 /* InstallationsSnippetsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF2A73E24A3D78300737F46 /* InstallationsSnippetsTests.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 8DF2A73B24A3D78300737F46 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 8DF2A71C24A3D78300737F46 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DF2A72324A3D78300737F46;
+ remoteInfo = InstallationsSnippets;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 8DC74B6324A3DABE004C5F44 /* InstallationsSnippets-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "InstallationsSnippets-Bridging-Header.h"; sourceTree = ""; };
+ 8DC74B6424A3DABF004C5F44 /* ObjCSnippets.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjCSnippets.h; sourceTree = ""; };
+ 8DC74B6524A3DABF004C5F44 /* ObjCSnippets.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCSnippets.m; sourceTree = ""; };
+ 8DF2A72424A3D78300737F46 /* InstallationsSnippets.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InstallationsSnippets.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8DF2A72724A3D78300737F46 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 8DF2A72924A3D78300737F46 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
+ 8DF2A72B24A3D78300737F46 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
+ 8DF2A72D24A3D78300737F46 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 8DF2A73024A3D78300737F46 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
+ 8DF2A73324A3D78300737F46 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 8DF2A73524A3D78300737F46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 8DF2A73A24A3D78300737F46 /* InstallationsSnippetsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InstallationsSnippetsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8DF2A73E24A3D78300737F46 /* InstallationsSnippetsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallationsSnippetsTests.swift; sourceTree = ""; };
+ 8DF2A74024A3D78300737F46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DF2A72124A3D78300737F46 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D7951C62D2C8A15000FD694 /* FirebaseInstallations in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8DF2A73724A3D78300737F46 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 8D7951C42D2C8A15000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 8DF2A71B24A3D78300737F46 = {
+ isa = PBXGroup;
+ children = (
+ 8DF2A72624A3D78300737F46 /* InstallationsSnippets */,
+ 8DF2A73D24A3D78300737F46 /* InstallationsSnippetsTests */,
+ 8D7951C42D2C8A15000FD694 /* Frameworks */,
+ 8DF2A72524A3D78300737F46 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 8DF2A72524A3D78300737F46 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DF2A72424A3D78300737F46 /* InstallationsSnippets.app */,
+ 8DF2A73A24A3D78300737F46 /* InstallationsSnippetsTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 8DF2A72624A3D78300737F46 /* InstallationsSnippets */ = {
+ isa = PBXGroup;
+ children = (
+ 8DF2A72724A3D78300737F46 /* AppDelegate.swift */,
+ 8DF2A72924A3D78300737F46 /* SceneDelegate.swift */,
+ 8DF2A72B24A3D78300737F46 /* ContentView.swift */,
+ 8DC74B6424A3DABF004C5F44 /* ObjCSnippets.h */,
+ 8DC74B6524A3DABF004C5F44 /* ObjCSnippets.m */,
+ 8DF2A72D24A3D78300737F46 /* Assets.xcassets */,
+ 8DF2A73224A3D78300737F46 /* LaunchScreen.storyboard */,
+ 8DF2A73524A3D78300737F46 /* Info.plist */,
+ 8DF2A72F24A3D78300737F46 /* Preview Content */,
+ 8DC74B6324A3DABE004C5F44 /* InstallationsSnippets-Bridging-Header.h */,
+ );
+ path = InstallationsSnippets;
+ sourceTree = "";
+ };
+ 8DF2A72F24A3D78300737F46 /* Preview Content */ = {
+ isa = PBXGroup;
+ children = (
+ 8DF2A73024A3D78300737F46 /* Preview Assets.xcassets */,
+ );
+ path = "Preview Content";
+ sourceTree = "";
+ };
+ 8DF2A73D24A3D78300737F46 /* InstallationsSnippetsTests */ = {
+ isa = PBXGroup;
+ children = (
+ 8DF2A73E24A3D78300737F46 /* InstallationsSnippetsTests.swift */,
+ 8DF2A74024A3D78300737F46 /* Info.plist */,
+ );
+ path = InstallationsSnippetsTests;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DF2A72324A3D78300737F46 /* InstallationsSnippets */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8DF2A74324A3D78300737F46 /* Build configuration list for PBXNativeTarget "InstallationsSnippets" */;
+ buildPhases = (
+ 8DF2A72024A3D78300737F46 /* Sources */,
+ 8DF2A72124A3D78300737F46 /* Frameworks */,
+ 8DF2A72224A3D78300737F46 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = InstallationsSnippets;
+ productName = InstallationsSnippets;
+ productReference = 8DF2A72424A3D78300737F46 /* InstallationsSnippets.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 8DF2A73924A3D78300737F46 /* InstallationsSnippetsTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8DF2A74624A3D78300737F46 /* Build configuration list for PBXNativeTarget "InstallationsSnippetsTests" */;
+ buildPhases = (
+ 8DF2A73624A3D78300737F46 /* Sources */,
+ 8DF2A73724A3D78300737F46 /* Frameworks */,
+ 8DF2A73824A3D78300737F46 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 8DF2A73C24A3D78300737F46 /* PBXTargetDependency */,
+ );
+ name = InstallationsSnippetsTests;
+ productName = InstallationsSnippetsTests;
+ productReference = 8DF2A73A24A3D78300737F46 /* InstallationsSnippetsTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 8DF2A71C24A3D78300737F46 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ LastSwiftUpdateCheck = 1140;
+ LastUpgradeCheck = 1610;
+ ORGANIZATIONNAME = Firebase;
+ TargetAttributes = {
+ 8DF2A72324A3D78300737F46 = {
+ CreatedOnToolsVersion = 11.4;
+ LastSwiftMigration = 1140;
+ };
+ 8DF2A73924A3D78300737F46 = {
+ CreatedOnToolsVersion = 11.4;
+ TestTargetID = 8DF2A72324A3D78300737F46;
+ };
+ };
+ };
+ buildConfigurationList = 8DF2A71F24A3D78300737F46 /* Build configuration list for PBXProject "InstallationsSnippets" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 8DF2A71B24A3D78300737F46;
+ packageReferences = (
+ 8D7951C32D2C89F0000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
+ productRefGroup = 8DF2A72524A3D78300737F46 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DF2A72324A3D78300737F46 /* InstallationsSnippets */,
+ 8DF2A73924A3D78300737F46 /* InstallationsSnippetsTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8DF2A72224A3D78300737F46 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DF2A73424A3D78300737F46 /* LaunchScreen.storyboard in Resources */,
+ 8DF2A73124A3D78300737F46 /* Preview Assets.xcassets in Resources */,
+ 8DF2A72E24A3D78300737F46 /* Assets.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8DF2A73824A3D78300737F46 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DF2A72024A3D78300737F46 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DF2A72824A3D78300737F46 /* AppDelegate.swift in Sources */,
+ 8DC74B6624A3DABF004C5F44 /* ObjCSnippets.m in Sources */,
+ 8DF2A72A24A3D78300737F46 /* SceneDelegate.swift in Sources */,
+ 8DF2A72C24A3D78300737F46 /* ContentView.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8DF2A73624A3D78300737F46 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DF2A73F24A3D78300737F46 /* InstallationsSnippetsTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 8DF2A73C24A3D78300737F46 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8DF2A72324A3D78300737F46 /* InstallationsSnippets */;
+ targetProxy = 8DF2A73B24A3D78300737F46 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 8DF2A73224A3D78300737F46 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8DF2A73324A3D78300737F46 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 8DF2A74124A3D78300737F46 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.4;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 8DF2A74224A3D78300737F46 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 8DF2A74424A3D78300737F46 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_ASSET_PATHS = "\"InstallationsSnippets/Preview Content\"";
+ ENABLE_PREVIEWS = YES;
+ INFOPLIST_FILE = InstallationsSnippets/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.InstallationsSnippets;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "InstallationsSnippets/InstallationsSnippets-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 8DF2A74524A3D78300737F46 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_ASSET_PATHS = "\"InstallationsSnippets/Preview Content\"";
+ ENABLE_PREVIEWS = YES;
+ INFOPLIST_FILE = InstallationsSnippets/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.InstallationsSnippets;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "InstallationsSnippets/InstallationsSnippets-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 8DF2A74724A3D78300737F46 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = InstallationsSnippetsTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.4;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.InstallationsSnippetsTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InstallationsSnippets.app/InstallationsSnippets";
+ };
+ name = Debug;
+ };
+ 8DF2A74824A3D78300737F46 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = InstallationsSnippetsTests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.4;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.InstallationsSnippetsTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InstallationsSnippets.app/InstallationsSnippets";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 8DF2A71F24A3D78300737F46 /* Build configuration list for PBXProject "InstallationsSnippets" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8DF2A74124A3D78300737F46 /* Debug */,
+ 8DF2A74224A3D78300737F46 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8DF2A74324A3D78300737F46 /* Build configuration list for PBXNativeTarget "InstallationsSnippets" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8DF2A74424A3D78300737F46 /* Debug */,
+ 8DF2A74524A3D78300737F46 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8DF2A74624A3D78300737F46 /* Build configuration list for PBXNativeTarget "InstallationsSnippetsTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8DF2A74724A3D78300737F46 /* Debug */,
+ 8DF2A74824A3D78300737F46 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951C32D2C89F0000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7951C52D2C8A15000FD694 /* FirebaseInstallations */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951C32D2C89F0000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseInstallations;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = 8DF2A71C24A3D78300737F46 /* Project object */;
+}
diff --git a/installations/InstallationsSnippets/AppDelegate.swift b/installations/InstallationsSnippets/AppDelegate.swift
new file mode 100644
index 00000000..f0d3cd6e
--- /dev/null
+++ b/installations/InstallationsSnippets/AppDelegate.swift
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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 FirebaseCore
+import FirebaseInstallations
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ FirebaseApp.configure()
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+ var installationIDObserver: NSObjectProtocol?
+ func handleInstallationIDChange() {
+ // [START handle_installation_id_change]
+ installationIDObserver = NotificationCenter.default.addObserver(
+ forName: .InstallationIDDidChange,
+ object: nil,
+ queue: nil
+ ) { (notification) in
+ // Fetch new Installation ID
+ Task {
+ await self.fetchInstallationToken()
+ }
+ }
+ // [END handle_installation_id_change]
+ }
+
+ func fetchInstallationID() async {
+ // [START fetch_installation_id]
+ do {
+ let id = try await Installations.installations().installationID()
+ print("Installation ID: \(id)")
+ } catch {
+ print("Error fetching id: \(error)")
+ }
+ // [END fetch_installation_id]
+ }
+
+ func fetchInstallationToken() async {
+ // [START fetch_installation_token]
+ do {
+ let result = try await Installations.installations()
+ .authTokenForcingRefresh(true)
+ print("Installation auth token: \(result.authToken)")
+ } catch {
+ print("Error fetching token: \(error)")
+ }
+ // [END fetch_installation_token]
+ }
+
+ func deleteInstallation() async {
+ // [START delete_installation]
+ do {
+ try await Installations.installations().delete()
+ print("Installation deleted");
+ } catch {
+ print("Error deleting installation: \(error)")
+ }
+ // [END delete_installation]
+ }
+
+}
+
diff --git a/installations/InstallationsSnippets/Assets.xcassets/AppIcon.appiconset/Contents.json b/installations/InstallationsSnippets/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..9221b9bb
--- /dev/null
+++ b/installations/InstallationsSnippets/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "scale" : "1x",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/installations/InstallationsSnippets/Assets.xcassets/Contents.json b/installations/InstallationsSnippets/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/installations/InstallationsSnippets/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/installations/InstallationsSnippets/Base.lproj/LaunchScreen.storyboard b/installations/InstallationsSnippets/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..865e9329
--- /dev/null
+++ b/installations/InstallationsSnippets/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installations/InstallationsSnippets/ContentView.swift b/installations/InstallationsSnippets/ContentView.swift
new file mode 100644
index 00000000..29e56014
--- /dev/null
+++ b/installations/InstallationsSnippets/ContentView.swift
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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 SwiftUI
+
+struct ContentView: View {
+ var body: some View {
+ Text("Hello, World!")
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
diff --git a/installations/InstallationsSnippets/Info.plist b/installations/InstallationsSnippets/Info.plist
new file mode 100644
index 00000000..9742bf0f
--- /dev/null
+++ b/installations/InstallationsSnippets/Info.plist
@@ -0,0 +1,60 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ $(PRODUCT_MODULE_NAME).SceneDelegate
+
+
+
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/installations/InstallationsSnippets/InstallationsSnippets-Bridging-Header.h b/installations/InstallationsSnippets/InstallationsSnippets-Bridging-Header.h
new file mode 100644
index 00000000..1b2cb5d6
--- /dev/null
+++ b/installations/InstallationsSnippets/InstallationsSnippets-Bridging-Header.h
@@ -0,0 +1,4 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
diff --git a/installations/InstallationsSnippets/ObjCSnippets.h b/installations/InstallationsSnippets/ObjCSnippets.h
new file mode 100644
index 00000000..92d86163
--- /dev/null
+++ b/installations/InstallationsSnippets/ObjCSnippets.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ObjCSnippets : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/installations/InstallationsSnippets/ObjCSnippets.m b/installations/InstallationsSnippets/ObjCSnippets.m
new file mode 100644
index 00000000..3c8b80a5
--- /dev/null
+++ b/installations/InstallationsSnippets/ObjCSnippets.m
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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 FirebaseInstallations;
+
+#import "ObjCSnippets.h"
+
+@interface ObjCSnippets ()
+@property(nonatomic, nullable) id installationIDObserver;
+@end
+
+@implementation ObjCSnippets
+
+- (void)handleInstallationIDChange {
+ // [START handle_installation_id_change]
+ __weak __auto_type weakSelf = self;
+ self.installationIDObserver = [[NSNotificationCenter defaultCenter]
+ addObserverForName: FIRInstallationIDDidChangeNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification * _Nonnull notification) {
+ // Fetch new Installation ID
+ [weakSelf fetchInstallationsID];
+ }];
+ // [END handle_installation_id_change]
+}
+
+- (void)fetchInstallationsID {
+ // [START fetch_installation_id]
+ [[FIRInstallations installations] installationIDWithCompletion:^(NSString *identifier, NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching Installation ID %@", error);
+ return;
+ }
+ NSLog(@"Installation ID: %@", identifier);
+ }];
+ // [END fetch_installation_id]
+}
+
+- (void)fetchInstallationsToken {
+ // [START fetch_installation_token]
+ [[FIRInstallations installations] authTokenForcingRefresh:true
+ completion:^(FIRInstallationsAuthTokenResult *result, NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error fetching Installation token %@", error);
+ return;
+ }
+ NSLog(@"Installation auth token: %@", [result authToken]);
+ }];
+ // [END fetch_installation_token]
+}
+
+- (void)deleteInstallations {
+ // [START delete_installation]
+ [[FIRInstallations installations] deleteWithCompletion:^(NSError *error) {
+ if (error != nil) {
+ NSLog(@"Error deleting Installation %@", error);
+ return;
+ }
+ NSLog(@"Installation deleted");
+ }];
+ // [END delete_installation]
+}
+
+@end
diff --git a/installations/InstallationsSnippets/Preview Content/Preview Assets.xcassets/Contents.json b/installations/InstallationsSnippets/Preview Content/Preview Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/installations/InstallationsSnippets/Preview Content/Preview Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/installations/InstallationsSnippets/SceneDelegate.swift b/installations/InstallationsSnippets/SceneDelegate.swift
new file mode 100644
index 00000000..a85e0eb5
--- /dev/null
+++ b/installations/InstallationsSnippets/SceneDelegate.swift
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2020 Google Inc.
+//
+// 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 SwiftUI
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ var window: UIWindow?
+
+
+ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+ // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+ // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+ // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+
+ // Create the SwiftUI view that provides the window contents.
+ let contentView = ContentView()
+
+ // Use a UIHostingController as window root view controller.
+ if let windowScene = scene as? UIWindowScene {
+ let window = UIWindow(windowScene: windowScene)
+ window.rootViewController = UIHostingController(rootView: contentView)
+ self.window = window
+ window.makeKeyAndVisible()
+ }
+ }
+
+ func sceneDidDisconnect(_ scene: UIScene) {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
+ }
+
+ func sceneDidBecomeActive(_ scene: UIScene) {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+ }
+
+ func sceneWillResignActive(_ scene: UIScene) {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+ }
+
+ func sceneWillEnterForeground(_ scene: UIScene) {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+ }
+
+ func sceneDidEnterBackground(_ scene: UIScene) {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+ }
+
+
+}
+
diff --git a/installations/InstallationsSnippetsTests/Info.plist b/installations/InstallationsSnippetsTests/Info.plist
new file mode 100644
index 00000000..64d65ca4
--- /dev/null
+++ b/installations/InstallationsSnippetsTests/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/installations/InstallationsSnippetsTests/InstallationsSnippetsTests.swift b/installations/InstallationsSnippetsTests/InstallationsSnippetsTests.swift
new file mode 100644
index 00000000..acbaf080
--- /dev/null
+++ b/installations/InstallationsSnippetsTests/InstallationsSnippetsTests.swift
@@ -0,0 +1,34 @@
+//
+// InstallationsSnippetsTests.swift
+// InstallationsSnippetsTests
+//
+// Created by Morgan Chen on 6/24/20.
+// Copyright © 2020 Firebase. All rights reserved.
+//
+
+import XCTest
+@testable import InstallationsSnippets
+
+class InstallationsSnippetsTests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() throws {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ func testPerformanceExample() throws {
+ // This is an example of a performance test case.
+ self.measure {
+ // Put the code you want to measure the time of here.
+ }
+ }
+
+}
diff --git a/invites/InvitesExample.xcodeproj/project.pbxproj b/invites/InvitesExample.xcodeproj/project.pbxproj
deleted file mode 100644
index 9f49bc09..00000000
--- a/invites/InvitesExample.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,920 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- 1073478F20315A0F004A66D1 /* InvitesExampleSwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1073478E20315A0F004A66D1 /* InvitesExampleSwiftUITests.swift */; };
- 1073485320333BDE004A66D1 /* InvitesExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1073485220333BDE004A66D1 /* InvitesExampleUITests.m */; };
- 4B1A6C781B0A752100E1EDA2 /* InvitesExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A6C771B0A752100E1EDA2 /* InvitesExampleTests.m */; };
- 4B1F2A361B01375C00F69A92 /* SignInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1F2A351B01375C00F69A92 /* SignInViewController.swift */; };
- 4B97B2591AD7145E0036DD6C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B97B2581AD7145E0036DD6C /* AppDelegate.swift */; };
- 4B97B25B1AD7145E0036DD6C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B97B25A1AD7145E0036DD6C /* ViewController.swift */; };
- 4BA30A161AE81F5A00E5CDE9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99E21ACF472000C4DC2C /* SystemConfiguration.framework */; };
- 4BA30A171AE81F5A00E5CDE9 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99E01ACF470F00C4DC2C /* MessageUI.framework */; };
- 4BA30A181AE81F5A00E5CDE9 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DE1ACF46FA00C4DC2C /* CoreMotion.framework */; };
- 4BA30A191AE81F5A00E5CDE9 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DC1ACF46F400C4DC2C /* CoreLocation.framework */; };
- 4BA30A1A1AE81F5A00E5CDE9 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DA1ACF46EC00C4DC2C /* AssetsLibrary.framework */; };
- 4BA30A1B1AE81F5A00E5CDE9 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99D81ACF46E500C4DC2C /* AddressBook.framework */; };
- 4BC032E41ACF33B70092326A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC032E31ACF33B70092326A /* main.m */; };
- 4BC032E71ACF33B70092326A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC032E61ACF33B70092326A /* AppDelegate.m */; };
- 4BC032EA1ACF33B70092326A /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC032E91ACF33B70092326A /* ViewController.m */; };
- 4BCF1C421AFBFA8D0039B15C /* SignInViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1C411AFBFA8D0039B15C /* SignInViewController.m */; };
- 4BDB99D91ACF46E500C4DC2C /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99D81ACF46E500C4DC2C /* AddressBook.framework */; };
- 4BDB99DB1ACF46EC00C4DC2C /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DA1ACF46EC00C4DC2C /* AssetsLibrary.framework */; };
- 4BDB99DD1ACF46F400C4DC2C /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DC1ACF46F400C4DC2C /* CoreLocation.framework */; };
- 4BDB99DF1ACF46FA00C4DC2C /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99DE1ACF46FA00C4DC2C /* CoreMotion.framework */; };
- 4BDB99E11ACF470F00C4DC2C /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99E01ACF470F00C4DC2C /* MessageUI.framework */; };
- 4BDB99E31ACF472000C4DC2C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDB99E21ACF472000C4DC2C /* SystemConfiguration.framework */; };
- EF4BB4D81B05B454003A1AC6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B5CBBFB1AE9DBF700D822CE /* Main.storyboard */; };
- EFB292011B0F1F430021C8AC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EFB291FD1B0F1F430021C8AC /* Images.xcassets */; };
- EFB292021B0F1F430021C8AC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EFB291FD1B0F1F430021C8AC /* Images.xcassets */; };
- EFB292031B0F1F430021C8AC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EFB291FE1B0F1F430021C8AC /* LaunchScreen.xib */; };
- EFB292041B0F1F430021C8AC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EFB291FE1B0F1F430021C8AC /* LaunchScreen.xib */; };
- EFB292061B0F20100021C8AC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B5CBBFB1AE9DBF700D822CE /* Main.storyboard */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXContainerItemProxy section */
- 1073479120315A0F004A66D1 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 4BC032D61ACF33B70092326A /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 4B97B2521AD7145E0036DD6C;
- remoteInfo = InvitesExampleSwift;
- };
- 1073485520333BDE004A66D1 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 4BC032D61ACF33B70092326A /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 4BC032DD1ACF33B70092326A;
- remoteInfo = InvitesExample;
- };
- 4B1A6C791B0A752100E1EDA2 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 4BC032D61ACF33B70092326A /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 4BC032DD1ACF33B70092326A;
- remoteInfo = AppInvitesExample;
- };
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXFileReference section */
- 105A4F501D91C5A500B5DE54 /* InvitesExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = InvitesExample.entitlements; sourceTree = ""; };
- 1073478C20315A0F004A66D1 /* InvitesExampleSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InvitesExampleSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 1073478E20315A0F004A66D1 /* InvitesExampleSwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesExampleSwiftUITests.swift; sourceTree = ""; };
- 1073479020315A0F004A66D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 1073485020333BDE004A66D1 /* InvitesExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InvitesExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 1073485220333BDE004A66D1 /* InvitesExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InvitesExampleUITests.m; sourceTree = ""; };
- 1073485420333BDE004A66D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 108F89D31D47B0090009615B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 4B1A6C731B0A752100E1EDA2 /* InvitesExample.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InvitesExample.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 4B1A6C771B0A752100E1EDA2 /* InvitesExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InvitesExampleTests.m; sourceTree = ""; };
- 4B1F2A351B01375C00F69A92 /* SignInViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignInViewController.swift; sourceTree = ""; };
- 4B5CBBFC1AE9DBF700D822CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
- 4B97B2531AD7145E0036DD6C /* InvitesExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InvitesExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 4B97B2581AD7145E0036DD6C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 4B97B25A1AD7145E0036DD6C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
- 4B97B25F1AD7145E0036DD6C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
- 4BC032DE1ACF33B70092326A /* InvitesExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InvitesExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 4BC032E31ACF33B70092326A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
- 4BC032E51ACF33B70092326A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
- 4BC032E61ACF33B70092326A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
- 4BC032E81ACF33B70092326A /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
- 4BC032E91ACF33B70092326A /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
- 4BCF1C411AFBFA8D0039B15C /* SignInViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignInViewController.m; sourceTree = ""; };
- 4BCF1C431AFC01A40039B15C /* SignInViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignInViewController.h; sourceTree = ""; };
- 4BDB99D81ACF46E500C4DC2C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
- 4BDB99DA1ACF46EC00C4DC2C /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
- 4BDB99DC1ACF46F400C4DC2C /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
- 4BDB99DE1ACF46FA00C4DC2C /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
- 4BDB99E01ACF470F00C4DC2C /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
- 4BDB99E21ACF472000C4DC2C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
- EFB291FD1B0F1F430021C8AC /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
- EFB291FE1B0F1F430021C8AC /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 1073478920315A0F004A66D1 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 1073484D20333BDE004A66D1 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B1A6C701B0A752100E1EDA2 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B97B2501AD7145E0036DD6C /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 4BA30A161AE81F5A00E5CDE9 /* SystemConfiguration.framework in Frameworks */,
- 4BA30A171AE81F5A00E5CDE9 /* MessageUI.framework in Frameworks */,
- 4BA30A181AE81F5A00E5CDE9 /* CoreMotion.framework in Frameworks */,
- 4BA30A191AE81F5A00E5CDE9 /* CoreLocation.framework in Frameworks */,
- 4BA30A1A1AE81F5A00E5CDE9 /* AssetsLibrary.framework in Frameworks */,
- 4BA30A1B1AE81F5A00E5CDE9 /* AddressBook.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4BC032DB1ACF33B70092326A /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 4BDB99E31ACF472000C4DC2C /* SystemConfiguration.framework in Frameworks */,
- 4BDB99E11ACF470F00C4DC2C /* MessageUI.framework in Frameworks */,
- 4BDB99DF1ACF46FA00C4DC2C /* CoreMotion.framework in Frameworks */,
- 4BDB99DD1ACF46F400C4DC2C /* CoreLocation.framework in Frameworks */,
- 4BDB99DB1ACF46EC00C4DC2C /* AssetsLibrary.framework in Frameworks */,
- 4BDB99D91ACF46E500C4DC2C /* AddressBook.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 1073478D20315A0F004A66D1 /* InvitesExampleSwiftUITests */ = {
- isa = PBXGroup;
- children = (
- 1073478E20315A0F004A66D1 /* InvitesExampleSwiftUITests.swift */,
- 1073479020315A0F004A66D1 /* Info.plist */,
- );
- path = InvitesExampleSwiftUITests;
- sourceTree = "";
- };
- 1073485120333BDE004A66D1 /* InvitesExampleUITests */ = {
- isa = PBXGroup;
- children = (
- 1073485220333BDE004A66D1 /* InvitesExampleUITests.m */,
- 1073485420333BDE004A66D1 /* Info.plist */,
- );
- path = InvitesExampleUITests;
- sourceTree = "";
- };
- 4B1A6C741B0A752100E1EDA2 /* InvitesExampleTests */ = {
- isa = PBXGroup;
- children = (
- 4B1A6C771B0A752100E1EDA2 /* InvitesExampleTests.m */,
- );
- path = InvitesExampleTests;
- sourceTree = "";
- };
- 4B97B2551AD7145E0036DD6C /* InvitesExampleSwift */ = {
- isa = PBXGroup;
- children = (
- 4B97B2581AD7145E0036DD6C /* AppDelegate.swift */,
- 4B1F2A351B01375C00F69A92 /* SignInViewController.swift */,
- 4B97B25A1AD7145E0036DD6C /* ViewController.swift */,
- 4B97B25F1AD7145E0036DD6C /* Images.xcassets */,
- );
- path = InvitesExampleSwift;
- sourceTree = "";
- };
- 4BC032D51ACF33B70092326A = {
- isa = PBXGroup;
- children = (
- 4BC032E01ACF33B70092326A /* InvitesExample */,
- 4B97B2551AD7145E0036DD6C /* InvitesExampleSwift */,
- 4B1A6C741B0A752100E1EDA2 /* InvitesExampleTests */,
- 1073478D20315A0F004A66D1 /* InvitesExampleSwiftUITests */,
- 1073485120333BDE004A66D1 /* InvitesExampleUITests */,
- 4BC032DF1ACF33B70092326A /* Products */,
- E27D599993EDB54E213FA076 /* Frameworks */,
- );
- sourceTree = "";
- };
- 4BC032DF1ACF33B70092326A /* Products */ = {
- isa = PBXGroup;
- children = (
- 4BC032DE1ACF33B70092326A /* InvitesExample.app */,
- 4B97B2531AD7145E0036DD6C /* InvitesExample.app */,
- 4B1A6C731B0A752100E1EDA2 /* InvitesExample.xctest */,
- 1073478C20315A0F004A66D1 /* InvitesExampleSwiftUITests.xctest */,
- 1073485020333BDE004A66D1 /* InvitesExampleUITests.xctest */,
- );
- name = Products;
- sourceTree = "";
- };
- 4BC032E01ACF33B70092326A /* InvitesExample */ = {
- isa = PBXGroup;
- children = (
- 105A4F501D91C5A500B5DE54 /* InvitesExample.entitlements */,
- 4BC032E51ACF33B70092326A /* AppDelegate.h */,
- 4BC032E61ACF33B70092326A /* AppDelegate.m */,
- 4BCF1C431AFC01A40039B15C /* SignInViewController.h */,
- 4BCF1C411AFBFA8D0039B15C /* SignInViewController.m */,
- 4BC032E81ACF33B70092326A /* ViewController.h */,
- 4BC032E91ACF33B70092326A /* ViewController.m */,
- 4BC032E11ACF33B70092326A /* Supporting Files */,
- );
- path = InvitesExample;
- sourceTree = "";
- };
- 4BC032E11ACF33B70092326A /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- 108F89D31D47B0090009615B /* Info.plist */,
- EFB291FB1B0F1F430021C8AC /* shared */,
- 4B5CBBFB1AE9DBF700D822CE /* Main.storyboard */,
- 4BC032E31ACF33B70092326A /* main.m */,
- );
- name = "Supporting Files";
- sourceTree = "";
- };
- E27D599993EDB54E213FA076 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- 4BDB99E21ACF472000C4DC2C /* SystemConfiguration.framework */,
- 4BDB99E01ACF470F00C4DC2C /* MessageUI.framework */,
- 4BDB99DE1ACF46FA00C4DC2C /* CoreMotion.framework */,
- 4BDB99DC1ACF46F400C4DC2C /* CoreLocation.framework */,
- 4BDB99DA1ACF46EC00C4DC2C /* AssetsLibrary.framework */,
- 4BDB99D81ACF46E500C4DC2C /* AddressBook.framework */,
- );
- name = Frameworks;
- sourceTree = "";
- };
- EFB291FB1B0F1F430021C8AC /* shared */ = {
- isa = PBXGroup;
- children = (
- EFB291FD1B0F1F430021C8AC /* Images.xcassets */,
- EFB291FE1B0F1F430021C8AC /* LaunchScreen.xib */,
- );
- name = shared;
- path = ../../shared;
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 1073478B20315A0F004A66D1 /* InvitesExampleSwiftUITests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 1073479320315A0F004A66D1 /* Build configuration list for PBXNativeTarget "InvitesExampleSwiftUITests" */;
- buildPhases = (
- 1073478820315A0F004A66D1 /* Sources */,
- 1073478920315A0F004A66D1 /* Frameworks */,
- 1073478A20315A0F004A66D1 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 1073479220315A0F004A66D1 /* PBXTargetDependency */,
- );
- name = InvitesExampleSwiftUITests;
- productName = InvitesExampleSwiftUITests;
- productReference = 1073478C20315A0F004A66D1 /* InvitesExampleSwiftUITests.xctest */;
- productType = "com.apple.product-type.bundle.ui-testing";
- };
- 1073484F20333BDE004A66D1 /* InvitesExampleUITests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 1073485720333BDE004A66D1 /* Build configuration list for PBXNativeTarget "InvitesExampleUITests" */;
- buildPhases = (
- 1073484C20333BDE004A66D1 /* Sources */,
- 1073484D20333BDE004A66D1 /* Frameworks */,
- 1073484E20333BDE004A66D1 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 1073485620333BDE004A66D1 /* PBXTargetDependency */,
- );
- name = InvitesExampleUITests;
- productName = InvitesExampleUITests;
- productReference = 1073485020333BDE004A66D1 /* InvitesExampleUITests.xctest */;
- productType = "com.apple.product-type.bundle.ui-testing";
- };
- 4B1A6C721B0A752100E1EDA2 /* InvitesExampleTests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 4B1A6C7D1B0A752100E1EDA2 /* Build configuration list for PBXNativeTarget "InvitesExampleTests" */;
- buildPhases = (
- 4B1A6C6F1B0A752100E1EDA2 /* Sources */,
- 4B1A6C701B0A752100E1EDA2 /* Frameworks */,
- 4B1A6C711B0A752100E1EDA2 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 4B1A6C7A1B0A752100E1EDA2 /* PBXTargetDependency */,
- );
- name = InvitesExampleTests;
- productName = AppInvitesExampleTests;
- productReference = 4B1A6C731B0A752100E1EDA2 /* InvitesExample.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- 4B97B2521AD7145E0036DD6C /* InvitesExampleSwift */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 4B97B2721AD7145E0036DD6C /* Build configuration list for PBXNativeTarget "InvitesExampleSwift" */;
- buildPhases = (
- 4B97B24F1AD7145E0036DD6C /* Sources */,
- 4B97B2511AD7145E0036DD6C /* Resources */,
- 4B97B2501AD7145E0036DD6C /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = InvitesExampleSwift;
- productName = AppInvitesExampleSwift;
- productReference = 4B97B2531AD7145E0036DD6C /* InvitesExample.app */;
- productType = "com.apple.product-type.application";
- };
- 4BC032DD1ACF33B70092326A /* InvitesExample */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 4BC033011ACF33B70092326A /* Build configuration list for PBXNativeTarget "InvitesExample" */;
- buildPhases = (
- 4BC032DA1ACF33B70092326A /* Sources */,
- 4BC032DC1ACF33B70092326A /* Resources */,
- 4BC032DB1ACF33B70092326A /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = InvitesExample;
- productName = AppInvitesExample;
- productReference = 4BC032DE1ACF33B70092326A /* InvitesExample.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 4BC032D61ACF33B70092326A /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 0930;
- ORGANIZATIONNAME = "Google Inc.";
- TargetAttributes = {
- 1073478B20315A0F004A66D1 = {
- CreatedOnToolsVersion = 9.2;
- LastSwiftMigration = 1000;
- ProvisioningStyle = Automatic;
- TestTargetID = 4B97B2521AD7145E0036DD6C;
- };
- 1073484F20333BDE004A66D1 = {
- CreatedOnToolsVersion = 9.2;
- ProvisioningStyle = Automatic;
- TestTargetID = 4BC032DD1ACF33B70092326A;
- };
- 4B1A6C721B0A752100E1EDA2 = {
- CreatedOnToolsVersion = 6.3.1;
- LastSwiftMigration = 0800;
- ProvisioningStyle = Automatic;
- TestTargetID = 4BC032DD1ACF33B70092326A;
- };
- 4B97B2521AD7145E0036DD6C = {
- LastSwiftMigration = 1000;
- ProvisioningStyle = Automatic;
- };
- 4BC032DD1ACF33B70092326A = {
- CreatedOnToolsVersion = 6.2;
- LastSwiftMigration = 0800;
- ProvisioningStyle = Automatic;
- };
- };
- };
- buildConfigurationList = 4BC032D91ACF33B70092326A /* Build configuration list for PBXProject "InvitesExample" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = 4BC032D51ACF33B70092326A;
- productRefGroup = 4BC032DF1ACF33B70092326A /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 4BC032DD1ACF33B70092326A /* InvitesExample */,
- 4B97B2521AD7145E0036DD6C /* InvitesExampleSwift */,
- 4B1A6C721B0A752100E1EDA2 /* InvitesExampleTests */,
- 1073478B20315A0F004A66D1 /* InvitesExampleSwiftUITests */,
- 1073484F20333BDE004A66D1 /* InvitesExampleUITests */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- 1073478A20315A0F004A66D1 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 1073484E20333BDE004A66D1 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B1A6C711B0A752100E1EDA2 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B97B2511AD7145E0036DD6C /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- EFB292061B0F20100021C8AC /* Main.storyboard in Resources */,
- EFB292041B0F1F430021C8AC /* LaunchScreen.xib in Resources */,
- EFB292021B0F1F430021C8AC /* Images.xcassets in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4BC032DC1ACF33B70092326A /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- EF4BB4D81B05B454003A1AC6 /* Main.storyboard in Resources */,
- EFB292011B0F1F430021C8AC /* Images.xcassets in Resources */,
- EFB292031B0F1F430021C8AC /* LaunchScreen.xib in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- 1073478820315A0F004A66D1 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 1073478F20315A0F004A66D1 /* InvitesExampleSwiftUITests.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 1073484C20333BDE004A66D1 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 1073485320333BDE004A66D1 /* InvitesExampleUITests.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B1A6C6F1B0A752100E1EDA2 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 4B1A6C781B0A752100E1EDA2 /* InvitesExampleTests.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4B97B24F1AD7145E0036DD6C /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 4B97B25B1AD7145E0036DD6C /* ViewController.swift in Sources */,
- 4B97B2591AD7145E0036DD6C /* AppDelegate.swift in Sources */,
- 4B1F2A361B01375C00F69A92 /* SignInViewController.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 4BC032DA1ACF33B70092326A /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 4BCF1C421AFBFA8D0039B15C /* SignInViewController.m in Sources */,
- 4BC032EA1ACF33B70092326A /* ViewController.m in Sources */,
- 4BC032E71ACF33B70092326A /* AppDelegate.m in Sources */,
- 4BC032E41ACF33B70092326A /* main.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
- 1073479220315A0F004A66D1 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 4B97B2521AD7145E0036DD6C /* InvitesExampleSwift */;
- targetProxy = 1073479120315A0F004A66D1 /* PBXContainerItemProxy */;
- };
- 1073485620333BDE004A66D1 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 4BC032DD1ACF33B70092326A /* InvitesExample */;
- targetProxy = 1073485520333BDE004A66D1 /* PBXContainerItemProxy */;
- };
- 4B1A6C7A1B0A752100E1EDA2 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 4BC032DD1ACF33B70092326A /* InvitesExample */;
- targetProxy = 4B1A6C791B0A752100E1EDA2 /* PBXContainerItemProxy */;
- };
-/* End PBXTargetDependency section */
-
-/* Begin PBXVariantGroup section */
- 4B5CBBFB1AE9DBF700D822CE /* Main.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- 4B5CBBFC1AE9DBF700D822CE /* Base */,
- );
- name = Main.storyboard;
- sourceTree = "";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- 1073479420315A0F004A66D1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- CODE_SIGN_STYLE = Automatic;
- DEBUG_INFORMATION_FORMAT = dwarf;
- GCC_C_LANGUAGE_STANDARD = gnu11;
- INFOPLIST_FILE = InvitesExampleSwiftUITests/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.2;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExampleSwiftUITests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
- SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.2;
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = InvitesExampleSwift;
- };
- name = Debug;
- };
- 1073479520315A0F004A66D1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- CODE_SIGN_STYLE = Automatic;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu11;
- INFOPLIST_FILE = InvitesExampleSwiftUITests/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.2;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExampleSwiftUITests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.2;
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = InvitesExampleSwift;
- };
- name = Release;
- };
- 1073485820333BDE004A66D1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- CODE_SIGN_STYLE = Automatic;
- DEBUG_INFORMATION_FORMAT = dwarf;
- GCC_C_LANGUAGE_STANDARD = gnu11;
- INFOPLIST_FILE = InvitesExampleUITests/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.2;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExampleUITests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = InvitesExample;
- };
- name = Debug;
- };
- 1073485920333BDE004A66D1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- CODE_SIGN_STYLE = Automatic;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu11;
- INFOPLIST_FILE = InvitesExampleUITests/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.2;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExampleUITests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = InvitesExample;
- };
- name = Release;
- };
- 4B1A6C7B1B0A752100E1EDA2 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- BUNDLE_LOADER = "$(TEST_HOST)";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = "";
- FRAMEWORK_SEARCH_PATHS = (
- "$(SDKROOT)/Developer/Library/Frameworks",
- "$(inherited)",
- );
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- INFOPLIST_FILE = InvitesExample/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 8.3;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "com.google.samples.quickstart.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE_SPECIFIER = "";
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InvitesExample.app/InvitesExample";
- };
- name = Debug;
- };
- 4B1A6C7C1B0A752100E1EDA2 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- BUNDLE_LOADER = "$(TEST_HOST)";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEVELOPMENT_TEAM = "";
- FRAMEWORK_SEARCH_PATHS = (
- "$(SDKROOT)/Developer/Library/Frameworks",
- "$(inherited)",
- );
- GCC_NO_COMMON_BLOCKS = YES;
- INFOPLIST_FILE = InvitesExample/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 8.3;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "com.google.samples.quickstart.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE_SPECIFIER = "";
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InvitesExample.app/InvitesExample";
- };
- name = Release;
- };
- 4B97B2731AD7145E0036DD6C /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_ENTITLEMENTS = InvitesExample/InvitesExample.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
- INFOPLIST_FILE = InvitesExample/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- LIBRARY_SEARCH_PATHS = "$(inherited)";
- ONLY_ACTIVE_ARCH = YES;
- OTHER_LDFLAGS = "$(inherited)";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExample;
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE_SPECIFIER = "";
- SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.0;
- VALID_ARCHS = "armv7 armv7s arm64";
- };
- name = Debug;
- };
- 4B97B2741AD7145E0036DD6C /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_ENTITLEMENTS = InvitesExample/InvitesExample.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
- INFOPLIST_FILE = InvitesExample/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- LIBRARY_SEARCH_PATHS = "$(inherited)";
- OTHER_LDFLAGS = "$(inherited)";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExample;
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE_SPECIFIER = "";
- SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
- SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.0;
- VALID_ARCHS = "armv7 armv7s arm64";
- };
- name = Release;
- };
- 4BC032FF1ACF33B70092326A /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- ENABLE_BITCODE = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.2;
- MTL_ENABLE_DEBUG_INFO = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- 4BC033001ACF33B70092326A /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- ENABLE_BITCODE = NO;
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.2;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
- TARGETED_DEVICE_FAMILY = "1,2";
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 4BC033021ACF33B70092326A /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CODE_SIGN_ENTITLEMENTS = InvitesExample/InvitesExample.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = InvitesExample/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExample;
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE = "";
- PROVISIONING_PROFILE_SPECIFIER = "";
- };
- name = Debug;
- };
- 4BC033031ACF33B70092326A /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CODE_SIGN_ENTITLEMENTS = InvitesExample/InvitesExample.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = InvitesExample/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.quickstart.InvitesExample;
- PRODUCT_NAME = InvitesExample;
- PROVISIONING_PROFILE_SPECIFIER = "";
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 1073479320315A0F004A66D1 /* Build configuration list for PBXNativeTarget "InvitesExampleSwiftUITests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1073479420315A0F004A66D1 /* Debug */,
- 1073479520315A0F004A66D1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 1073485720333BDE004A66D1 /* Build configuration list for PBXNativeTarget "InvitesExampleUITests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1073485820333BDE004A66D1 /* Debug */,
- 1073485920333BDE004A66D1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 4B1A6C7D1B0A752100E1EDA2 /* Build configuration list for PBXNativeTarget "InvitesExampleTests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 4B1A6C7B1B0A752100E1EDA2 /* Debug */,
- 4B1A6C7C1B0A752100E1EDA2 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 4B97B2721AD7145E0036DD6C /* Build configuration list for PBXNativeTarget "InvitesExampleSwift" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 4B97B2731AD7145E0036DD6C /* Debug */,
- 4B97B2741AD7145E0036DD6C /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 4BC032D91ACF33B70092326A /* Build configuration list for PBXProject "InvitesExample" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 4BC032FF1ACF33B70092326A /* Debug */,
- 4BC033001ACF33B70092326A /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 4BC033011ACF33B70092326A /* Build configuration list for PBXNativeTarget "InvitesExample" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 4BC033021ACF33B70092326A /* Debug */,
- 4BC033031ACF33B70092326A /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 4BC032D61ACF33B70092326A /* Project object */;
-}
diff --git a/invites/InvitesExample/AppDelegate.m b/invites/InvitesExample/AppDelegate.m
deleted file mode 100644
index 71a3eab2..00000000
--- a/invites/InvitesExample/AppDelegate.m
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 "AppDelegate.h"
-@import Firebase;
-@import GoogleSignIn;
-
-@implementation AppDelegate
-
-// [START configure]
-- (BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- // Use Firebase library to configure APIs
- [FIRApp configure];
- return YES;
-}
-// [END configure]
-
-// [START openurl]
-- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
- options:(NSDictionary *)options {
- return [self application:app
- openURL:url
- sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
- annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
-}
-
-- (BOOL)application:(UIApplication *)application
- openURL:(NSURL *)url
- sourceApplication:(NSString *)sourceApplication
- annotation:(id)annotation {
- if ([[GIDSignIn sharedInstance] handleURL:url
- sourceApplication:sourceApplication
- annotation:annotation]) {
- return YES;
- }
- // Handle App Invite requests
- return [FIRInvites handleUniversalLink:url
- completion:^(FIRReceivedInvite * _Nullable receivedInvite,
- NSError * _Nullable error) {
- // [START_EXCLUDE]
- if (receivedInvite) {
- [self showAlertViewWithInvite:receivedInvite];
- }
- // [END_EXCLUDE]
- }];
-}
-// [END openurl]
-
-// [START continueuseractivity]
-- (BOOL)application:(UIApplication *)application
-continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:
-#if defined(__IPHONE_12_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0)
-(nonnull void (^)(NSArray> *_Nullable))restorationHandler {
-#else
- (nonnull void (^)(NSArray *_Nullable))restorationHandler {
-#endif // __IPHONE_12_0
- // Handle App Invite requests
- return [FIRInvites handleUniversalLink:userActivity.webpageURL
- completion:^(FIRReceivedInvite * _Nullable receivedInvite,
- NSError * _Nullable error) {
- // [START_EXCLUDE]
- if (receivedInvite) {
- [self showAlertViewWithInvite:receivedInvite];
- }
- // [END_EXCLUDE]
- }];
-}
-// [END continueuseractivity]
-
-- (void)showAlertViewWithInvite:(FIRReceivedInvite *)invite {
- UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK"
- style:UIAlertActionStyleDefault
- handler:nil];
- NSString *matchType = invite.matchType == FIRReceivedInviteMatchTypeWeak ? @"weak" : @"strong";
- NSString *message =
- [NSString stringWithFormat:@"Invite ID: %@\nDeep-link: %@\nMatch Type: %@",
- invite.inviteId, invite.deepLink, matchType];
-
- UIAlertController *alertController =
- [UIAlertController alertControllerWithTitle:@"Invite"
- message:message
- preferredStyle:UIAlertControllerStyleAlert];
- [alertController addAction:okAction];
- [self.window.rootViewController presentViewController:alertController
- animated:YES
- completion:nil];
-}
-@end
diff --git a/invites/InvitesExample/Base.lproj/Main.storyboard b/invites/InvitesExample/Base.lproj/Main.storyboard
deleted file mode 100644
index e94cae05..00000000
--- a/invites/InvitesExample/Base.lproj/Main.storyboard
+++ /dev/null
@@ -1,238 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Roboto-Bold
-
-
- Roboto-Regular
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/invites/InvitesExample/SignInViewController.m b/invites/InvitesExample/SignInViewController.m
deleted file mode 100644
index d0a7857b..00000000
--- a/invites/InvitesExample/SignInViewController.m
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 "SignInViewController.h"
-#import "ViewController.h"
-@import GoogleSignIn;
-@import Firebase;
-
-
-@interface SignInViewController ()
-@property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
-@property(weak, nonatomic) IBOutlet UILabel *bgText;
-@end
-
-@implementation SignInViewController
-
-- (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
-
- _bgText.text = @"Invites\niOS demo";
-
- [GIDSignIn sharedInstance].clientID = [FIRApp defaultApp].options.clientID;
-
- // Sign the user in automatically
- [GIDSignIn sharedInstance].uiDelegate = self;
- [[GIDSignIn sharedInstance] signInSilently];
-
- // TODO(developer): Configure the sign-in button look/feel
- [GIDSignIn sharedInstance].delegate = self;
-}
-
-- (void)signIn:(GIDSignIn *)signIn
- didSignInForUser:(GIDGoogleUser *)user
- withError:(NSError *)error {
- if (error == nil) {
- // User Successfully signed in.
- // TODO: Remove async after, when GIDSignIn is started getting called after dissmissVC
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.35 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self performSegueWithIdentifier:@"SignedInScreen" sender:self];
- });
- } else {
- // Something went wrong; for example, the user could haved clicked cancel.
- NSLog(@"%@", error.localizedDescription);
- }
-}
-
-- (UIStatusBarStyle)preferredStatusBarStyle {
- return UIStatusBarStyleLightContent;
-}
-
-- (IBAction)unwindToSignIn:(UIStoryboardSegue *)sender {
- [GIDSignIn sharedInstance].delegate = self;
-}
-@end
diff --git a/invites/InvitesExample/ViewController.m b/invites/InvitesExample/ViewController.m
deleted file mode 100644
index e6b6e70a..00000000
--- a/invites/InvitesExample/ViewController.m
+++ /dev/null
@@ -1,172 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 "ViewController.h"
-@import GoogleSignIn;
-@import Firebase;
-
-// [START viewcontroller_interfaces]
-@interface ViewController ()
-// [END viewcontroller_interfaces]
-// [START viewcontroller_vars]
-@property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
-@property(weak, nonatomic) IBOutlet UIButton *signOutButton;
-@property(weak, nonatomic) IBOutlet UIButton *disconnectButton;
-@property(weak, nonatomic) IBOutlet UIButton *inviteButton;
-@property(weak, nonatomic) IBOutlet UILabel *statusText;
-// [END viewcontroler_vars]
-@end
-
-@implementation ViewController
-
-// [START viewdidload]
-- (void)viewDidLoad {
- [super viewDidLoad];
-
- // TODO(developer) Configure the sign-in button look/feel
- [GIDSignIn sharedInstance].delegate = self;
- [GIDSignIn sharedInstance].uiDelegate = self;
-
- // Sign in automatically.
- [[GIDSignIn sharedInstance] signInSilently];
-
- [self setupUI];
- [self toggleAuthUI];
-}
-// [END viewdidload]
-
-- (void)setupUI {
- float grayValue = (204.0 / 255);
- UIColor *grayColor = [UIColor colorWithRed:grayValue green:grayValue blue:grayValue alpha:1.0];
-
- _inviteButton.layer.cornerRadius = 3;
- _inviteButton.layer.shadowRadius = 1;
- _inviteButton.layer.shadowOffset = CGSizeMake(0, 0.5);
- _inviteButton.layer.shadowColor = [UIColor blackColor].CGColor;
- _inviteButton.layer.shadowOpacity = .7;
-
- _signOutButton.layer.borderWidth = .5;
- _signOutButton.layer.borderColor = grayColor.CGColor;
- _signOutButton.layer.cornerRadius = 2;
- _signOutButton.layer.shadowRadius = .5;
- _signOutButton.layer.shadowOffset = CGSizeMake(0, 0.5);
- _signOutButton.layer.shadowColor = [UIColor blackColor].CGColor;
- _signOutButton.layer.shadowOpacity = .4;
-
- _disconnectButton.layer.borderWidth = .5;
- _disconnectButton.layer.borderColor = grayColor.CGColor;
- _disconnectButton.layer.cornerRadius = 2;
- _disconnectButton.layer.shadowRadius = .5;
- _disconnectButton.layer.shadowOffset = CGSizeMake(0, 0.5);
- _disconnectButton.layer.shadowColor = [UIColor blackColor].CGColor;
- _disconnectButton.layer.shadowOpacity = .4;
-}
-
-// [START signin_handler]
-- (void)signIn:(GIDSignIn *)signIn
- didSignInForUser:(GIDGoogleUser *)user
- withError:(NSError *)error {
- // Perform any operations on signed in user here.
- if (user.profile.name) {
- _statusText.text = [NSString stringWithFormat:@"Signed in as %@", user.profile.name];
- } else {
- _statusText.text = @"Signed in, profile name is not set";
- }
- [self toggleAuthUI];
-}
-// [END signin_handler]
-
-// [START disconnect_handler]
-- (void)signIn:(GIDSignIn *)signIn
- didDisconnectWithUser:(GIDGoogleUser *)user
- withError:(NSError *)error {
- // Perform any operations when the user disconnects from app here.
- _statusText.text = @"Disconnected user";
- [self toggleAuthUI];
-}
-// [END disconnect_handler]
-
-// [START signout_tapped]
-- (IBAction)signOutTapped:(id)sender {
- [[GIDSignIn sharedInstance] signOut];
- _statusText.text = @"Signed out";
- [self toggleAuthUI];
-}
-// [END signout_tapped]
-
-// [START disconnect_tapped]
-- (IBAction)disconnectTapped:(id)sender {
- [[GIDSignIn sharedInstance] disconnect];
-}
-// [END disconnect_tapped]
-
-// [START invite_tapped]
-- (IBAction)inviteTapped:(id)sender {
- id inviteDialog = [FIRInvites inviteDialog];
- [inviteDialog setInviteDelegate:self];
-
- // NOTE: You must have the App Store ID set in your developer console project
- // in order for invitations to successfully be sent.
- NSString *message =
- [NSString stringWithFormat:@"Try this out!\n -%@",
- [GIDSignIn sharedInstance].currentUser.profile.name];
-
- // A message hint for the dialog. Note this manifests differently depending on the
- // received invitation type. For example, in an email invite this appears as the subject.
- [inviteDialog setMessage:message];
-
- // Title for the dialog, this is what the user sees before sending the invites.
- [inviteDialog setTitle:@"Invites Example"];
- [inviteDialog setDeepLink:@"app_url"];
- [inviteDialog setCallToActionText:@"Install!"];
- [inviteDialog setCustomImage:@"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"];
- [inviteDialog open];
-}
-// [END invite_tapped]
-
-// [START invite_finished]
-- (void)inviteFinishedWithInvitations:(NSArray *)invitationIds error:(NSError *)error {
- if (error) {
- NSLog(@"%@", error.localizedDescription);
- } else {
- NSLog(@"%li invites sent", invitationIds.count);
- }
-}
-// [END invite_finished]
-
-// [START toggle_auth]
-- (void)toggleAuthUI {
- if ([GIDSignIn sharedInstance].currentUser.authentication == nil) {
- // Not signed in
- _signInButton.enabled = YES;
- _signOutButton.enabled = NO;
- _disconnectButton.enabled = NO;
- _inviteButton.enabled = NO;
- [self performSegueWithIdentifier:@"SignedOutScreen" sender:self];
- } else {
- // Signed in
- _signInButton.enabled = NO;
- _signOutButton.enabled = YES;
- _disconnectButton.enabled = YES;
- _inviteButton.enabled = YES;
- }
-}
-// [END toggle_auth]
-
-- (UIStatusBarStyle)preferredStatusBarStyle {
- return UIStatusBarStyleLightContent;
-}
-@end
diff --git a/invites/InvitesExampleSwift/AppDelegate.swift b/invites/InvitesExampleSwift/AppDelegate.swift
deleted file mode 100644
index 39c085c7..00000000
--- a/invites/InvitesExampleSwift/AppDelegate.swift
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 Firebase
-import GoogleSignIn
-
-@UIApplicationMain
-class AppDelegate: UIResponder, UIApplicationDelegate {
- var window: UIWindow?
-
- // [START configure]
- func application(_ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
- // Use Firebase library to configure APIs
- FirebaseApp.configure()
- return true
- }
- // [END configure]
-
- // [START openurl]
- @available(iOS 9.0, *)
- func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
- return self.application(application, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String, annotation: "")
- }
-
- func application(_ application: UIApplication,
- open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
- if GIDSignIn.sharedInstance().handle(url, sourceApplication: sourceApplication, annotation: annotation) {
- return true
- }
-
- return Invites.handleUniversalLink(url) { invite, error in
- // [START_EXCLUDE]
- if let error = error {
- print(error.localizedDescription)
- return
- }
- if let invite = invite {
- self.showAlertView(withInvite: invite)
- }
- // [END_EXCLUDE]
- }
- }
- // [END openurl]
-
- // [START continueuseractivity]
- func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
- return Invites.handleUniversalLink(userActivity.webpageURL!) { invite, error in
- // [START_EXCLUDE]
- if let error = error {
- print(error.localizedDescription)
- return
- }
- if let invite = invite {
- self.showAlertView(withInvite: invite)
- }
- // [END_EXCLUDE]
- }
- }
- // [END continueuseractivity]
-
- func showAlertView(withInvite invite: ReceivedInvite) {
- let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
- let matchType = invite.matchType == .weak ? "weak" : "strong"
- let message = "Invite ID: \(invite.inviteId)\nDeep-link: \(invite.deepLink)\nMatch Type: \(matchType)"
- let alertController = UIAlertController(title: "Invite", message: message, preferredStyle: .alert)
- alertController.addAction(okAction)
- self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
- }
-}
-
diff --git a/invites/InvitesExampleSwift/SignInViewController.swift b/invites/InvitesExampleSwift/SignInViewController.swift
deleted file mode 100644
index 0194820d..00000000
--- a/invites/InvitesExampleSwift/SignInViewController.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 Firebase
-import GoogleSignIn
-
-// Match the ObjC symbol name inside Main.storyboard.
-@objc(SignInViewController)
-
-class SignInViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {
-
- @IBOutlet weak var signInButton: GIDSignInButton!
- @IBOutlet weak var bgText: UILabel!
-
- override func viewDidAppear(_ animated: Bool) {
- super.viewDidAppear(animated)
-
- bgText.text = "Invites\niOS demo"
-
- GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
- GIDSignIn.sharedInstance().delegate = self
- GIDSignIn.sharedInstance().uiDelegate = self
- GIDSignIn.sharedInstance().signInSilently()
- }
-
- func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
- guard error == nil else {
- // Something went wrong; for example, the user could haved clicked cancel.
- print("\(error.localizedDescription)")
- return
- }
- // User Successfully signed in.
- // TODO: Remove async after, when GIDSignIn is started getting called after dissmissVC
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
- self.performSegue(withIdentifier: "SignedInScreen", sender: self)
- }
- }
-
- @IBAction func unwindToSignIn(_ sender: UIStoryboardSegue) {
- GIDSignIn.sharedInstance().delegate = self
- }
-
- // Sets the status bar to white.
- override var preferredStatusBarStyle: UIStatusBarStyle {
- return .lightContent
- }
-}
diff --git a/invites/InvitesExampleSwift/ViewController.swift b/invites/InvitesExampleSwift/ViewController.swift
deleted file mode 100644
index 837eef95..00000000
--- a/invites/InvitesExampleSwift/ViewController.swift
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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 GoogleSignIn
-import Firebase
-
-// Match the ObjC symbol name inside Main.storyboard.
-@objc(ViewController)
-// [START viewcontroller_interfaces]
-class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate, InviteDelegate {
-// [END viewcontroller_interfaces]
- // [START viewcontroller_vars]
- @IBOutlet weak var signOutButton: UIButton!
- @IBOutlet weak var disconnectButton: UIButton!
- @IBOutlet weak var inviteButton: UIButton!
- @IBOutlet weak var statusText: UILabel!
- // [END viewcontroller_vars]
-
- // [START viewdidload]
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- GIDSignIn.sharedInstance().delegate = self
- GIDSignIn.sharedInstance().uiDelegate = self
- GIDSignIn.sharedInstance().signInSilently()
- toggleAuthUI()
- }
- // [END viewdidload]
-
- // [START signin_handler]
- func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
- if let error = error {
- print("\(error.localizedDescription)")
- } else {
- // User Successfully signed in.
- if let name = user.profile.name {
- statusText.text = "Signed in as \(name)"
- } else {
- statusText.text = "Signed in, profile name is not set"
- }
- }
- toggleAuthUI()
- }
- // [END signin_handler]
-
- // [START signout_tapped]
- @IBAction func signOutTapped(_ sender: AnyObject) {
- GIDSignIn.sharedInstance().signOut()
- statusText.text = "Signed out"
- toggleAuthUI()
- }
- // [END signout_tapped]
-
- // [START disconnect_tapped]
- @IBAction func disconnectTapped(_ sender: AnyObject) {
- GIDSignIn.sharedInstance().disconnect()
- statusText.text = "Disconnected"
- toggleAuthUI()
- }
-
- func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
- toggleAuthUI()
- }
- // [END disconnect_tapped]
-
- // [START invite_tapped]
- @IBAction func inviteTapped(_ sender: AnyObject) {
- if let invite = Invites.inviteDialog() {
- invite.setInviteDelegate(self)
-
- // NOTE: You must have the App Store ID set in your developer console project
- // in order for invitations to successfully be sent.
-
- // A message hint for the dialog. Note this manifests differently depending on the
- // received invitation type. For example, in an email invite this appears as the subject.
- invite.setMessage("Try this out!\n -\(GIDSignIn.sharedInstance().currentUser.profile.name)")
- // Title for the dialog, this is what the user sees before sending the invites.
- invite.setTitle("Invites Example")
- invite.setDeepLink("app_url")
- invite.setCallToActionText("Install!")
- invite.setCustomImage("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")
- invite.open()
- }
- }
- // [END invite_tapped]
-
- // [START toggle_auth]
- func toggleAuthUI() {
- if GIDSignIn.sharedInstance().hasAuthInKeychain() {
- // Signed in
- signOutButton.isEnabled = true
- disconnectButton.isEnabled = true
- inviteButton.isEnabled = true
- } else {
- signOutButton.isEnabled = false
- disconnectButton.isEnabled = false
- inviteButton.isEnabled = false
- self.performSegue(withIdentifier: "SignedOutScreen", sender:self)
- }
- }
- // [END toggle_auth]
-
- // [START invite_finished]
- func inviteFinished(withInvitations invitationIds: [String], error: Error?) {
- if let error = error {
- print("Failed: " + error.localizedDescription)
- } else {
- print("\(invitationIds.count) invites sent")
- }
- }
- // [END invite_finished]
-
- // Sets the status bar to white.
- override var preferredStatusBarStyle: UIStatusBarStyle {
- return UIStatusBarStyle.lightContent
- }
-}
diff --git a/invites/InvitesExampleSwiftUITests/InvitesExampleSwiftUITests.swift b/invites/InvitesExampleSwiftUITests/InvitesExampleSwiftUITests.swift
deleted file mode 100644
index b33f5428..00000000
--- a/invites/InvitesExampleSwiftUITests/InvitesExampleSwiftUITests.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// InvitesExampleSwiftUITests.swift
-// InvitesExampleSwiftUITests
-//
-// Created by Ibrahim Ulukaya on 2/12/18.
-// Copyright © 2018 Google Inc. All rights reserved.
-//
-
-import XCTest
-
-class InvitesExampleSwiftUITests: XCTestCase {
-
- override func setUp() {
- super.setUp()
-
- // Put setup code here. This method is called before the invocation of each test method in the class.
-
- // In UI tests it is usually best to stop immediately when a failure occurs.
- continueAfterFailure = false
- // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
- XCUIApplication().launch()
-
- // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
- }
-
- override func tearDown() {
- // Put teardown code here. This method is called after the invocation of each test method in the class.
- super.tearDown()
- }
-
- func testExample() {
- // Use recording to get started writing UI tests.
- // Use XCTAssert and related functions to verify your tests produce the correct results.
- }
-
-}
diff --git a/invites/InvitesExampleTests/InvitesExampleTests.m b/invites/InvitesExampleTests/InvitesExampleTests.m
deleted file mode 100644
index ce8e581b..00000000
--- a/invites/InvitesExampleTests/InvitesExampleTests.m
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (c) Google Inc.
-//
-// 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
-#import
-@import Firebase;
-
-@interface InvitesExampleTests : XCTestCase
-
-@end
-
-@implementation InvitesExampleTests
-
-- (void)testAppWasConfigured {
- // Check that the FIROptions matches what we read from the file.
- [FIRApp configure];
- NSDictionary *configPlist =
- [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
- pathForResource:@"GoogleService-Info"
- ofType:@"plist"]];
-
- // Check the client ID is configured for iOS target app.
- NSString* actual = [FIRApp defaultApp].options.clientID;
- NSString* expected = configPlist[@"CLIENT_ID"];
-
- XCTAssertEqualObjects(actual, expected);
-}
-
-@end
diff --git a/invites/Podfile b/invites/Podfile
deleted file mode 100644
index 7d5b6695..00000000
--- a/invites/Podfile
+++ /dev/null
@@ -1,11 +0,0 @@
-use_frameworks!
-platform :ios, '8.0'
-pod 'Firebase/Core'
-pod 'Firebase/Invites'
-
-target 'InvitesExample' do
-end
-target 'InvitesExampleSwift' do
-end
-target 'InvitesExampleTests' do
-end
diff --git a/invites/Podfile.lock b/invites/Podfile.lock
deleted file mode 100644
index 546ef389..00000000
--- a/invites/Podfile.lock
+++ /dev/null
@@ -1,154 +0,0 @@
-PODS:
- - Firebase/Core (5.20.2):
- - Firebase/CoreOnly
- - FirebaseAnalytics (= 5.8.1)
- - Firebase/CoreOnly (5.20.2):
- - FirebaseCore (= 5.4.1)
- - Firebase/Invites (5.20.2):
- - Firebase/CoreOnly
- - FirebaseInvites (= 3.0.1)
- - FirebaseAnalytics (5.8.1):
- - FirebaseCore (~> 5.4)
- - FirebaseInstanceID (~> 3.8)
- - GoogleAppMeasurement (= 5.8.1)
- - GoogleUtilities/AppDelegateSwizzler (~> 5.2)
- - GoogleUtilities/MethodSwizzler (~> 5.2)
- - GoogleUtilities/Network (~> 5.2)
- - "GoogleUtilities/NSData+zlib (~> 5.2)"
- - nanopb (~> 0.3)
- - FirebaseAnalyticsInterop (1.4.0)
- - FirebaseCore (5.4.1):
- - GoogleUtilities/Environment (~> 5.2)
- - GoogleUtilities/Logger (~> 5.2)
- - FirebaseDynamicLinks (3.4.3):
- - FirebaseAnalytics (~> 5.1)
- - FirebaseAnalyticsInterop (~> 1.0)
- - FirebaseCore (~> 5.2)
- - FirebaseInstanceID (3.8.1):
- - FirebaseCore (~> 5.2)
- - GoogleUtilities/Environment (~> 5.2)
- - GoogleUtilities/UserDefaults (~> 5.2)
- - FirebaseInvites (3.0.1):
- - FirebaseAnalytics (~> 5.1)
- - FirebaseDynamicLinks (~> 3.0)
- - GoogleAPIClientForREST (~> 1.0)
- - GoogleSignIn (~> 4.2)
- - GoogleToolboxForMac/Logger (~> 2.1)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- - "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- - GoogleToolboxForMac/StringEncoding (~> 2.1)
- - GoogleToolboxForMac/URLBuilder (~> 2.1)
- - GTMOAuth2 (~> 1.0)
- - GTMSessionFetcher/Core (~> 1.1)
- - GTMSessionFetcher/Full (~> 1.1)
- - Protobuf (~> 3.5)
- - GoogleAPIClientForREST (1.3.10):
- - GoogleAPIClientForREST/Core (= 1.3.10)
- - GTMSessionFetcher (>= 1.1.7)
- - GoogleAPIClientForREST/Core (1.3.10):
- - GTMSessionFetcher (>= 1.1.7)
- - GoogleAppMeasurement (5.8.1):
- - GoogleUtilities/AppDelegateSwizzler (~> 5.2)
- - GoogleUtilities/MethodSwizzler (~> 5.2)
- - GoogleUtilities/Network (~> 5.2)
- - "GoogleUtilities/NSData+zlib (~> 5.2)"
- - nanopb (~> 0.3)
- - GoogleSignIn (4.4.0):
- - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- - "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- - GTMSessionFetcher/Core (~> 1.1)
- - GoogleToolboxForMac/Core (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - GoogleToolboxForMac/DebugUtils (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - GoogleToolboxForMac/Defines (2.2.1)
- - GoogleToolboxForMac/Logger (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (2.2.1)":
- - GoogleToolboxForMac/DebugUtils (= 2.2.1)
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSString+URLArguments (= 2.2.1)"
- - "GoogleToolboxForMac/NSString+URLArguments (2.2.1)"
- - GoogleToolboxForMac/StringEncoding (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - GoogleToolboxForMac/URLBuilder (2.2.1):
- - GoogleToolboxForMac/Core (= 2.2.1)
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (= 2.2.1)"
- - "GoogleToolboxForMac/NSString+URLArguments (= 2.2.1)"
- - GoogleUtilities/AppDelegateSwizzler (5.8.0):
- - GoogleUtilities/Environment
- - GoogleUtilities/Logger
- - GoogleUtilities/Network
- - GoogleUtilities/Environment (5.8.0)
- - GoogleUtilities/Logger (5.8.0):
- - GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (5.8.0):
- - GoogleUtilities/Logger
- - GoogleUtilities/Network (5.8.0):
- - GoogleUtilities/Logger
- - "GoogleUtilities/NSData+zlib"
- - GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (5.8.0)"
- - GoogleUtilities/Reachability (5.8.0):
- - GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (5.8.0):
- - GoogleUtilities/Logger
- - GTMOAuth2 (1.1.6):
- - GTMSessionFetcher (~> 1.1)
- - GTMSessionFetcher (1.2.2):
- - GTMSessionFetcher/Full (= 1.2.2)
- - GTMSessionFetcher/Core (1.2.2)
- - GTMSessionFetcher/Full (1.2.2):
- - GTMSessionFetcher/Core (= 1.2.2)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
- - Protobuf (3.9.0)
-
-DEPENDENCIES:
- - Firebase/Core
- - Firebase/Invites
-
-SPEC REPOS:
- https://github.com/cocoapods/specs.git:
- - Firebase
- - FirebaseAnalytics
- - FirebaseAnalyticsInterop
- - FirebaseCore
- - FirebaseDynamicLinks
- - FirebaseInstanceID
- - FirebaseInvites
- - GoogleAPIClientForREST
- - GoogleAppMeasurement
- - GoogleSignIn
- - GoogleToolboxForMac
- - GoogleUtilities
- - GTMOAuth2
- - GTMSessionFetcher
- - nanopb
- - Protobuf
-
-SPEC CHECKSUMS:
- Firebase: 0c8cf33f266410c61ab3e2265cfa412200351d9c
- FirebaseAnalytics: ece1aa57a4f43c64d53a648b5a5e05151aae947b
- FirebaseAnalyticsInterop: d48b6ab67bcf016a05e55b71fc39c61c0cb6b7f3
- FirebaseCore: f1a9a8be1aee4bf71a2fc0f4096df6788bdfda61
- FirebaseDynamicLinks: f7a8717e2c7ea652923882a2d60b0045d6fd99d5
- FirebaseInstanceID: a122b0c258720cf250551bb2bedf48c699f80d90
- FirebaseInvites: f13ed69fae140e705baec1a59ff127334b841a8a
- GoogleAPIClientForREST: 4acfffd77f1c3c8741b6be9eaed0e603278efbde
- GoogleAppMeasurement: ffe513e90551844a739e7bcbb1d2aca1c28a4338
- GoogleSignIn: 7ff245e1a7b26d379099d3243a562f5747e23d39
- GoogleToolboxForMac: b3553629623a3b1bff17f555e736cd5a6d95ad55
- GoogleUtilities: 04fce34bcd5620c1ee76fb79172105c74a4df335
- GTMOAuth2: e8b6512c896235149df975c41d9a36c868ab7fba
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
- Protobuf: 1097ca58584c8d9be81bfbf2c5ff5975648dd87a
-
-PODFILE CHECKSUM: 95b5db7fdcb60afeb38ea4713dda46fe9aa0fb56
-
-COCOAPODS: 1.7.5
diff --git a/invites/README.md b/invites/README.md
deleted file mode 100644
index 40a80b03..00000000
--- a/invites/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Firebase Invites
-
-Firebase Invites is deprecated. You can create cross-platform invitation links that survive app installation using [Firebase Dynamic Links][fdl]. Please see [Migration Guide][migration] for more details.
-
-For an example of how to use Dynamic Links to invite users to your application, see [Invite Users to Your App][user-to-user].
-
-[fdl]:https://firebase.google.com/docs/dynamic-links/
-[migration]:https://firebase.google.com/docs/invites/deprecation
-[user-to-user]:https://firebase.google.com/docs/dynamic-links/use-cases/user-to-user
diff --git a/invites/Screenshot/app-invites-sample.png b/invites/Screenshot/app-invites-sample.png
deleted file mode 100644
index ffcd244b..00000000
Binary files a/invites/Screenshot/app-invites-sample.png and /dev/null differ
diff --git a/ml-functions/MLFunctionsExample.xcodeproj/project.pbxproj b/ml-functions/MLFunctionsExample.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..7a47ff3e
--- /dev/null
+++ b/ml-functions/MLFunctionsExample.xcodeproj/project.pbxproj
@@ -0,0 +1,527 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8D7951CA2D2C8AAA000FD694 /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951C92D2C8AAA000FD694 /* FirebaseFunctions */; };
+ 8D7951CC2D2C8AB2000FD694 /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = 8D7951CB2D2C8AB2000FD694 /* FirebaseFunctions */; };
+ 8D8FA34322F4CAB100213E06 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34222F4CAB100213E06 /* AppDelegate.m */; };
+ 8D8FA34622F4CAB100213E06 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA34522F4CAB100213E06 /* ViewController.m */; };
+ 8D8FA34922F4CAB100213E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34722F4CAB100213E06 /* Main.storyboard */; };
+ 8D8FA34B22F4CAB200213E06 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */; };
+ 8D8FA34E22F4CAB200213E06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */; };
+ 8D8FA35122F4CAB200213E06 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35022F4CAB200213E06 /* main.m */; };
+ 8D8FA35E22F4CAF700213E06 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */; };
+ 8D8FA36022F4CAF700213E06 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8FA35F22F4CAF700213E06 /* ViewController.swift */; };
+ 8D8FA36322F4CAF700213E06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36122F4CAF700213E06 /* Main.storyboard */; };
+ 8D8FA36522F4CAF800213E06 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36422F4CAF800213E06 /* Assets.xcassets */; };
+ 8D8FA36822F4CAF800213E06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 8D8FA33E22F4CAB100213E06 /* MLFunctionsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MLFunctionsExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D8FA34122F4CAB100213E06 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 8D8FA34222F4CAB100213E06 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 8D8FA34422F4CAB100213E06 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
+ 8D8FA34522F4CAB100213E06 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
+ 8D8FA34822F4CAB100213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 8D8FA34D22F4CAB200213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 8D8FA34F22F4CAB200213E06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 8D8FA35022F4CAB200213E06 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 8D8FA35B22F4CAF700213E06 /* MLFunctionsExampleSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MLFunctionsExampleSwift.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 8D8FA35F22F4CAF700213E06 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 8D8FA36222F4CAF700213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 8D8FA36422F4CAF800213E06 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 8D8FA36722F4CAF800213E06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 8D8FA36922F4CAF800213E06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D8FA33B22F4CAB100213E06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D7951CA2D2C8AAA000FD694 /* FirebaseFunctions in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35822F4CAF700213E06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D7951CC2D2C8AB2000FD694 /* FirebaseFunctions in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 8D7951C82D2C8AAA000FD694 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 8D8FA33522F4CAB100213E06 = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA34022F4CAB100213E06 /* MLFunctionsExample */,
+ 8D8FA35C22F4CAF700213E06 /* MLFunctionsExampleSwift */,
+ 8D7951C82D2C8AAA000FD694 /* Frameworks */,
+ 8D8FA33F22F4CAB100213E06 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 8D8FA33F22F4CAB100213E06 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA33E22F4CAB100213E06 /* MLFunctionsExample.app */,
+ 8D8FA35B22F4CAF700213E06 /* MLFunctionsExampleSwift.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 8D8FA34022F4CAB100213E06 /* MLFunctionsExample */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA34122F4CAB100213E06 /* AppDelegate.h */,
+ 8D8FA34222F4CAB100213E06 /* AppDelegate.m */,
+ 8D8FA34422F4CAB100213E06 /* ViewController.h */,
+ 8D8FA34522F4CAB100213E06 /* ViewController.m */,
+ 8D8FA34722F4CAB100213E06 /* Main.storyboard */,
+ 8D8FA34A22F4CAB200213E06 /* Assets.xcassets */,
+ 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */,
+ 8D8FA34F22F4CAB200213E06 /* Info.plist */,
+ 8D8FA35022F4CAB200213E06 /* main.m */,
+ );
+ path = MLFunctionsExample;
+ sourceTree = "";
+ };
+ 8D8FA35C22F4CAF700213E06 /* MLFunctionsExampleSwift */ = {
+ isa = PBXGroup;
+ children = (
+ 8D8FA35D22F4CAF700213E06 /* AppDelegate.swift */,
+ 8D8FA35F22F4CAF700213E06 /* ViewController.swift */,
+ 8D8FA36122F4CAF700213E06 /* Main.storyboard */,
+ 8D8FA36422F4CAF800213E06 /* Assets.xcassets */,
+ 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */,
+ 8D8FA36922F4CAF800213E06 /* Info.plist */,
+ );
+ path = MLFunctionsExampleSwift;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D8FA33D22F4CAB100213E06 /* MLFunctionsExample */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8D8FA35422F4CAB200213E06 /* Build configuration list for PBXNativeTarget "MLFunctionsExample" */;
+ buildPhases = (
+ 8D8FA33A22F4CAB100213E06 /* Sources */,
+ 8D8FA33B22F4CAB100213E06 /* Frameworks */,
+ 8D8FA33C22F4CAB100213E06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = MLFunctionsExample;
+ productName = MLFunctionsExample;
+ productReference = 8D8FA33E22F4CAB100213E06 /* MLFunctionsExample.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 8D8FA35A22F4CAF700213E06 /* MLFunctionsExampleSwift */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8D8FA36C22F4CAF800213E06 /* Build configuration list for PBXNativeTarget "MLFunctionsExampleSwift" */;
+ buildPhases = (
+ 8D8FA35722F4CAF700213E06 /* Sources */,
+ 8D8FA35822F4CAF700213E06 /* Frameworks */,
+ 8D8FA35922F4CAF700213E06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = MLFunctionsExampleSwift;
+ productName = MLFunctionsExampleSwift;
+ productReference = 8D8FA35B22F4CAF700213E06 /* MLFunctionsExampleSwift.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 8D8FA33622F4CAB100213E06 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ LastSwiftUpdateCheck = 1020;
+ LastUpgradeCheck = 1610;
+ ORGANIZATIONNAME = Firebase;
+ TargetAttributes = {
+ 8D8FA33D22F4CAB100213E06 = {
+ CreatedOnToolsVersion = 10.2;
+ };
+ 8D8FA35A22F4CAF700213E06 = {
+ CreatedOnToolsVersion = 10.2;
+ };
+ };
+ };
+ buildConfigurationList = 8D8FA33922F4CAB100213E06 /* Build configuration list for PBXProject "MLFunctionsExample" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 8D8FA33522F4CAB100213E06;
+ packageReferences = (
+ 8D7951C72D2C8A9B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
+ );
+ productRefGroup = 8D8FA33F22F4CAB100213E06 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D8FA33D22F4CAB100213E06 /* MLFunctionsExample */,
+ 8D8FA35A22F4CAF700213E06 /* MLFunctionsExampleSwift */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D8FA33C22F4CAB100213E06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA34E22F4CAB200213E06 /* LaunchScreen.storyboard in Resources */,
+ 8D8FA34B22F4CAB200213E06 /* Assets.xcassets in Resources */,
+ 8D8FA34922F4CAB100213E06 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35922F4CAF700213E06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA36822F4CAF800213E06 /* LaunchScreen.storyboard in Resources */,
+ 8D8FA36522F4CAF800213E06 /* Assets.xcassets in Resources */,
+ 8D8FA36322F4CAF700213E06 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D8FA33A22F4CAB100213E06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA34622F4CAB100213E06 /* ViewController.m in Sources */,
+ 8D8FA35122F4CAB200213E06 /* main.m in Sources */,
+ 8D8FA34322F4CAB100213E06 /* AppDelegate.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8D8FA35722F4CAF700213E06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D8FA36022F4CAF700213E06 /* ViewController.swift in Sources */,
+ 8D8FA35E22F4CAF700213E06 /* AppDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 8D8FA34722F4CAB100213E06 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA34822F4CAB100213E06 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA34C22F4CAB200213E06 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA34D22F4CAB200213E06 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA36122F4CAF700213E06 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA36222F4CAF700213E06 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 8D8FA36622F4CAF800213E06 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8D8FA36722F4CAF800213E06 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 8D8FA35222F4CAB200213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.2;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 8D8FA35322F4CAB200213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.2;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 8D8FA35522F4CAB200213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = MLFunctionsExample/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.MLFunctionsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 8D8FA35622F4CAB200213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = MLFunctionsExample/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.MLFunctionsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 8D8FA36A22F4CAF800213E06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = MLFunctionsExampleSwift/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.MLFunctionsExampleSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 8D8FA36B22F4CAF800213E06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ INFOPLIST_FILE = MLFunctionsExampleSwift/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.firebase.MLFunctionsExampleSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 8D8FA33922F4CAB100213E06 /* Build configuration list for PBXProject "MLFunctionsExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA35222F4CAB200213E06 /* Debug */,
+ 8D8FA35322F4CAB200213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8D8FA35422F4CAB200213E06 /* Build configuration list for PBXNativeTarget "MLFunctionsExample" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA35522F4CAB200213E06 /* Debug */,
+ 8D8FA35622F4CAB200213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8D8FA36C22F4CAF800213E06 /* Build configuration list for PBXNativeTarget "MLFunctionsExampleSwift" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D8FA36A22F4CAF800213E06 /* Debug */,
+ 8D8FA36B22F4CAF800213E06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D7951C72D2C8A9B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 11.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D7951C92D2C8AAA000FD694 /* FirebaseFunctions */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951C72D2C8A9B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFunctions;
+ };
+ 8D7951CB2D2C8AB2000FD694 /* FirebaseFunctions */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D7951C72D2C8A9B000FD694 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
+ productName = FirebaseFunctions;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = 8D8FA33622F4CAB100213E06 /* Project object */;
+}
diff --git a/ml-functions/MLFunctionsExample/AppDelegate.h b/ml-functions/MLFunctionsExample/AppDelegate.h
new file mode 100644
index 00000000..a9861fa2
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/AppDelegate.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/ml-functions/MLFunctionsExample/AppDelegate.m b/ml-functions/MLFunctionsExample/AppDelegate.m
new file mode 100644
index 00000000..69381fe8
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/AppDelegate.m
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseCore;
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [FIRApp configure];
+ return YES;
+}
+
+
+@end
diff --git a/ml-functions/MLFunctionsExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/ml-functions/MLFunctionsExample/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..d8db8d65
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ml-functions/MLFunctionsExample/Assets.xcassets/Contents.json b/ml-functions/MLFunctionsExample/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ml-functions/MLFunctionsExample/Base.lproj/LaunchScreen.storyboard b/ml-functions/MLFunctionsExample/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..bfa36129
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ml-functions/MLFunctionsExample/Base.lproj/Main.storyboard b/ml-functions/MLFunctionsExample/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..942f0bc4
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ml-functions/MLFunctionsExample/Info.plist b/ml-functions/MLFunctionsExample/Info.plist
new file mode 100644
index 00000000..16be3b68
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/ml-functions/MLFunctionsExample/ViewController.h b/ml-functions/MLFunctionsExample/ViewController.h
new file mode 100644
index 00000000..f543b8a0
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/ViewController.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/ml-functions/MLFunctionsExample/ViewController.m b/ml-functions/MLFunctionsExample/ViewController.m
new file mode 100644
index 00000000..2d5b80c9
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/ViewController.m
@@ -0,0 +1,169 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseFunctions;
+
+#import "ViewController.h"
+
+@interface ViewController ()
+// [START ml_functions_define]
+@property(strong, nonatomic) FIRFunctions *functions;
+// [END ml_functions_define]
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // [START ml_functions_init]
+ self.functions = [FIRFunctions functions];
+ // [END ml_functions_init]
+}
+
+- (void)prepareData:(UIImage *)uiImage {
+ // [START base64encodeImage]
+ NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
+ NSString *base64encodedImage =
+ [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
+ // [END base64encodeImage]
+}
+
+- (void)prepareLabelData:(NSString *)base64encodedImage {
+ // [START prepareLabelData]
+ NSDictionary *requestData = @{
+ @"image": @{@"content": base64encodedImage},
+ @"features": @{@"maxResults": @5, @"type": @"LABEL_DETECTION"}
+ };
+ // [END prepareLabelData]
+}
+
+- (void)prepareTextData:(NSString *)base64encodedImage {
+ // [START prepareTextData]
+ NSDictionary *requestData = @{
+ @"image": @{@"content": base64encodedImage},
+ @"features": @{@"type": @"TEXT_DETECTION"},
+ @"imageContext": @{@"languageHints": @[@"en"]}
+ };
+ // [END prepareTextData]
+ NSDictionary *textDataWithHints = @{
+ @"image": @{@"content": base64encodedImage},
+ @"features": @{@"type": @"TEXT_DETECTION"},
+ @"imageContext": @{@"languageHints": @[@"en"]}
+ };
+ NSDictionary *documentTextData = @{
+ @"image": @{@"content": base64encodedImage},
+ @"features": @{@"type": @"DOCUMENT_TEXT_DETECTION"}
+ };
+}
+
+- (void)prepareLandmarkData:(NSString *)base64encodedImage {
+ // [START prepareLandmarkData]
+ NSDictionary *requestData = @{
+ @"image": @{@"content": base64encodedImage},
+ @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"}
+ };
+ // [END prepareLandmarkData]
+}
+
+- (void)annotateImage:(NSDictionary *)requestData {
+
+ // [START function_annotateImage]
+ [[_functions HTTPSCallableWithName:@"annotateImage"]
+ callWithObject:requestData
+ completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
+ if (error) {
+ if ([error.domain isEqualToString:@"com.firebase.functions"]) {
+ FIRFunctionsErrorCode code = error.code;
+ NSString *message = error.localizedDescription;
+ NSObject *details = error.userInfo[@"details"];
+ }
+ // ...
+ }
+ // Function completed succesfully
+ // Get information about labeled objects
+
+ }];
+ // [END function_annotateImage]
+}
+
+- (void)getLabeledObjectsFromResult:(FIRHTTPSCallableResult *)result {
+ // [START getLabeledObjectsFrom]
+ NSArray *labelArray = result.data[@"labelAnnotations"];
+ for (NSDictionary *labelObj in labelArray) {
+ NSString *text = labelObj[@"description"];
+ NSString *entityId = labelObj[@"mid"];
+ NSNumber *confidence = labelObj[@"score"];
+ }
+ // [END getLabeledObjectsFrom]
+}
+
+- (void)getRecognizedTextsFromResult:(FIRHTTPSCallableResult *)result {
+ // [START getRecognizedTextsFrom]
+ NSDictionary *annotation = result.data[@"fullTextAnnotation"];
+ if (!annotation) { return; }
+ NSLog(@"\nComplete annotation:");
+ NSLog(@"\n%@", annotation[@"text"]);
+ // [END getRecognizedTextsFrom]
+
+ // [START getRecognizedTextsFrom_details]
+ for (NSDictionary *page in annotation[@"pages"]) {
+ NSMutableString *pageText = [NSMutableString new];
+ for (NSDictionary *block in page[@"blocks"]) {
+ NSMutableString *blockText = [NSMutableString new];
+ for (NSDictionary *paragraph in block[@"paragraphs"]) {
+ NSMutableString *paragraphText = [NSMutableString new];
+ for (NSDictionary *word in paragraph[@"words"]) {
+ NSMutableString *wordText = [NSMutableString new];
+ for (NSDictionary *symbol in word[@"symbols"]) {
+ NSString *text = symbol[@"text"];
+ [wordText appendString:text];
+ NSLog(@"Symbol text: %@ (confidence: %@\n", text, symbol[@"confidence"]);
+ }
+ NSLog(@"Word text: %@ (confidence: %@\n\n", wordText, word[@"confidence"]);
+ NSLog(@"Word bounding box: %@\n", word[@"boundingBox"]);
+ [paragraphText appendString:wordText];
+ }
+ NSLog(@"\nParagraph: \n%@\n", paragraphText);
+ NSLog(@"Paragraph bounding box: %@\n", paragraph[@"boundingBox"]);
+ NSLog(@"Paragraph Confidence: %@\n", paragraph[@"confidence"]);
+ [blockText appendString:paragraphText];
+ }
+ [pageText appendString:blockText];
+ }
+ }
+ // [END getRecognizedTextsFrom_details]
+}
+
+- (void)getRecognizedLandmarksFromResult:(FIRHTTPSCallableResult *)result {
+ // [START getRecognizedLandmarksFrom]
+ NSArray *labelArray = result.data[@"landmarkAnnotations"];
+ for (NSDictionary *labelObj in labelArray) {
+ NSString *landmarkName = labelObj[@"description"];
+ NSString *entityId = labelObj[@"mid"];
+ NSNumber *score = labelObj[@"score"];
+ NSArray *bounds = labelObj[@"boundingPoly"];
+ // Multiple locations are possible, e.g., the location of the depicted
+ // landmark and the location the picture was taken.
+ NSArray *locations = labelObj[@"locations"];
+ for (NSDictionary *location in locations) {
+ NSNumber *latitude = location[@"latLng"][@"latitude"];
+ NSNumber *longitude = location[@"latLng"][@"longitude"];
+ }
+ }
+ // [END getRecognizedLandmarksFrom]
+}
+
+@end
diff --git a/ml-functions/MLFunctionsExample/main.m b/ml-functions/MLFunctionsExample/main.m
new file mode 100644
index 00000000..8d31108d
--- /dev/null
+++ b/ml-functions/MLFunctionsExample/main.m
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/ml-functions/MLFunctionsExampleSwift/AppDelegate.swift b/ml-functions/MLFunctionsExampleSwift/AppDelegate.swift
new file mode 100644
index 00000000..26ad4232
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/AppDelegate.swift
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 Firebase
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ FirebaseApp.configure()
+ return true
+ }
+
+}
+
diff --git a/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json b/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..d8db8d65
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/Contents.json b/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/ml-functions/MLFunctionsExampleSwift/Base.lproj/LaunchScreen.storyboard b/ml-functions/MLFunctionsExampleSwift/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..bfa36129
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ml-functions/MLFunctionsExampleSwift/Base.lproj/Main.storyboard b/ml-functions/MLFunctionsExampleSwift/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..f1bcf384
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ml-functions/MLFunctionsExampleSwift/Info.plist b/ml-functions/MLFunctionsExampleSwift/Info.plist
new file mode 100644
index 00000000..16be3b68
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/ml-functions/MLFunctionsExampleSwift/ViewController.swift b/ml-functions/MLFunctionsExampleSwift/ViewController.swift
new file mode 100644
index 00000000..37204bce
--- /dev/null
+++ b/ml-functions/MLFunctionsExampleSwift/ViewController.swift
@@ -0,0 +1,174 @@
+//
+// Copyright (c) 2019 Google Inc.
+//
+// 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 FirebaseFunctions
+
+class ViewController: UIViewController {
+ // [START ml_functions_define]
+ lazy var functions = Functions.functions()
+ // [START ml_functions_define]
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+ func prepareData(uiImage: UIImage) {
+ // [START base64encodeImage]
+ guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return }
+ let base64encodedImage = imageData.base64EncodedString()
+ // [END base64encodeImage]
+ }
+
+ func prepareLabelData(base64encodedImage: String) {
+ // [START prepareLabelData]
+ let requestData = [
+ "image": ["content": base64encodedImage],
+ "features": ["maxResults": 5, "type": "LABEL_DETECTION"]
+ ]
+ // [END prepareLabelData]
+ }
+
+ func prepareTextData(base64encodedImage: String) {
+ let textDataWithHints = [
+ "image": ["content": base64encodedImage],
+ "features": ["type": "TEXT_DETECTION"],
+ "imageContext": ["languageHints": ["en"]]
+ ]
+ let documentTextData = [
+ "image": ["content": base64encodedImage],
+ "features": ["type": "DOCUMENT_TEXT_DETECTION"]
+ ]
+ // [START prepareTextData]
+ let requestData = [
+ "image": ["content": base64encodedImage],
+ "features": ["type": "TEXT_DETECTION"],
+ "imageContext": ["languageHints": ["en"]]
+ ]
+ // [END prepareTextData]
+ }
+
+ func prepareLandmarkData(base64encodedImage: String) {
+ // [START prepareLandmarkData]
+ let requestData = [
+ "image": ["content": base64encodedImage],
+ "features": ["maxResults": 5, "type": "LANDMARK_DETECTION"]
+ ]
+ // [END prepareLandmarkData]
+ }
+
+ func annotateImage(requestData: Any) async {
+ // [START function_annotateImage]
+ do {
+ let result = try await functions.httpsCallable("annotateImage").call(requestData)
+ print(result)
+ } catch {
+ if let error = error as NSError? {
+ if error.domain == FunctionsErrorDomain {
+ let code = FunctionsErrorCode(rawValue: error.code)
+ let message = error.localizedDescription
+ let details = error.userInfo[FunctionsErrorDetailsKey]
+ }
+ // ...
+ }
+ }
+ // [END function_annotateImage]
+ }
+
+ func getLabeledObjectsFrom(_ result: HTTPSCallableResult?) {
+ // [START getLabeledObjectsFrom]
+ if let labelArray = (result?.data as? [String: Any])?["labelAnnotations"] as? [[String:Any]] {
+ for labelObj in labelArray {
+ let text = labelObj["description"]
+ let entityId = labelObj["mid"]
+ let confidence = labelObj["score"]
+ }
+ }
+ // [END getLabeledObjectsFrom]
+ }
+
+ func getRecognizedTextsFrom(_ result: HTTPSCallableResult?) {
+ // [START function_getRecognizedTexts]
+ let annotation = result.flatMap { $0.data as? [String: Any] }
+ .flatMap { $0["fullTextAnnotation"] }
+ .flatMap { $0 as? [String: Any] }
+ guard let annotation = annotation else { return }
+
+ if let text = annotation["text"] as? String {
+ print("Complete annotation: \(text)")
+ }
+ // [END function_getRecognizedTexts]
+
+ // [START function_getRecognizedTexts_details]
+ guard let pages = annotation["pages"] as? [[String: Any]] else { return }
+ for page in pages {
+ var pageText = ""
+ guard let blocks = page["blocks"] as? [[String: Any]] else { continue }
+ for block in blocks {
+ var blockText = ""
+ guard let paragraphs = block["paragraphs"] as? [[String: Any]] else { continue }
+ for paragraph in paragraphs {
+ var paragraphText = ""
+ guard let words = paragraph["words"] as? [[String: Any]] else { continue }
+ for word in words {
+ var wordText = ""
+ guard let symbols = word["symbols"] as? [[String: Any]] else { continue }
+ for symbol in symbols {
+ let text = symbol["text"] as? String ?? ""
+ let confidence = symbol["confidence"] as? Float ?? 0.0
+ wordText += text
+ print("Symbol text: \(text) (confidence: \(confidence)%n")
+ }
+ let confidence = word["confidence"] as? Float ?? 0.0
+ print("Word text: \(wordText) (confidence: \(confidence)%n%n")
+ let boundingBox = word["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
+ print("Word bounding box: \(boundingBox.description)%n")
+ paragraphText += wordText
+ }
+ print("%nParagraph: %n\(paragraphText)%n")
+ let boundingBox = paragraph["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
+ print("Paragraph bounding box: \(boundingBox)%n")
+ let confidence = paragraph["confidence"] as? Float ?? 0.0
+ print("Paragraph Confidence: \(confidence)%n")
+ blockText += paragraphText
+ }
+ pageText += blockText
+ }
+ }
+ // [END function_getRecognizedTexts_details]
+ }
+
+ func getRecognizedLandmarksFrom(_ result: HTTPSCallableResult?) {
+ // [START getRecognizedLandmarksFrom]
+ if let labelArray = (result?.data as? [String: Any])?["landmarkAnnotations"] as? [[String:Any]] {
+ for labelObj in labelArray {
+ let landmarkName = labelObj["description"]
+ let entityId = labelObj["mid"]
+ let score = labelObj["score"]
+ let bounds = labelObj["boundingPoly"]
+ // Multiple locations are possible, e.g., the location of the depicted
+ // landmark and the location the picture was taken.
+ guard let locations = labelObj["locations"] as? [[String: [String: Any]]] else { continue }
+ for location in locations {
+ let latitude = location["latLng"]?["latitude"]
+ let longitude = location["latLng"]?["longitude"]
+ }
+ }
+ }
+ // [END getRecognizedLandmarksFrom]
+ }
+}
diff --git a/mlkit/Podfile.lock b/mlkit/Podfile.lock
index 0add4796..55f2c6d8 100644
--- a/mlkit/Podfile.lock
+++ b/mlkit/Podfile.lock
@@ -1,137 +1,134 @@
PODS:
- - Firebase/CoreOnly (6.8.0):
- - FirebaseCore (= 6.2.2)
- - Firebase/MLVision (6.8.0):
+ - Firebase/CoreOnly (6.34.0):
+ - FirebaseCore (= 6.10.4)
+ - Firebase/MLVision (6.34.0):
- Firebase/CoreOnly
- - FirebaseMLVision (~> 0.18.0)
- - Firebase/MLVisionAutoML (6.8.0):
+ - FirebaseMLVision (~> 0.21.0)
+ - Firebase/MLVisionAutoML (6.34.0):
- Firebase/CoreOnly
- - FirebaseMLVisionAutoML (~> 0.18.0)
- - FirebaseCore (6.2.2):
- - FirebaseCoreDiagnostics (~> 1.0)
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnostics (1.0.1):
- - FirebaseCoreDiagnosticsInterop (~> 1.0)
- - GoogleDataTransportCCTSupport (~> 1.0)
- - GoogleUtilities/Environment (~> 6.2)
- - GoogleUtilities/Logger (~> 6.2)
- - FirebaseCoreDiagnosticsInterop (1.0.0)
- - FirebaseInstanceID (4.2.4):
- - FirebaseCore (~> 6.0)
- - GoogleUtilities/Environment (~> 6.0)
- - GoogleUtilities/UserDefaults (~> 6.0)
- - FirebaseMLCommon (0.18.0):
- - FirebaseCore (~> 6.2)
- - FirebaseInstanceID (~> 4.2)
+ - FirebaseMLVisionAutoML (~> 0.21.0)
+ - FirebaseCore (6.10.4):
+ - FirebaseCoreDiagnostics (~> 1.6)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/Logger (~> 6.7)
+ - FirebaseCoreDiagnostics (1.7.0):
+ - GoogleDataTransport (~> 7.4)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/Logger (~> 6.7)
+ - nanopb (~> 1.30906.0)
+ - FirebaseInstallations (1.7.0):
+ - FirebaseCore (~> 6.10)
+ - GoogleUtilities/Environment (~> 6.7)
+ - GoogleUtilities/UserDefaults (~> 6.7)
+ - PromisesObjC (~> 1.2)
+ - FirebaseMLCommon (0.21.0):
+ - FirebaseCore (~> 6.9)
+ - FirebaseInstallations (~> 1.5)
- GoogleToolboxForMac/Logger (~> 2.1)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- GoogleUtilities/UserDefaults (~> 6.0)
- GTMSessionFetcher/Core (~> 1.1)
- - Protobuf (~> 3.5)
- - FirebaseMLVision (0.18.0):
- - FirebaseCore (~> 6.2)
- - FirebaseMLCommon (~> 0.18)
+ - Protobuf (~> 3.12)
+ - FirebaseMLVision (0.21.0):
+ - FirebaseCore (~> 6.9)
+ - FirebaseMLCommon (~> 0.21)
- GoogleAPIClientForREST/Core (~> 1.3)
- GoogleAPIClientForREST/Vision (~> 1.3)
- GoogleToolboxForMac/Logger (~> 2.1)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- GTMSessionFetcher/Core (~> 1.1)
- - Protobuf (~> 3.5)
- - FirebaseMLVisionAutoML (0.18.0):
- - FirebaseCore (~> 6.2)
- - FirebaseMLCommon (~> 0.18)
- - FirebaseMLVision (~> 0.18)
+ - Protobuf (~> 3.12)
+ - FirebaseMLVisionAutoML (0.21.0):
+ - FirebaseCore (~> 6.9)
+ - FirebaseMLCommon (~> 0.21)
+ - FirebaseMLVision (~> 0.21)
- GTMSessionFetcher/Core (~> 1.1)
- - TensorFlowLiteObjC (~> 1.14.0)
- - GoogleAPIClientForREST/Core (1.3.10):
- - GTMSessionFetcher (>= 1.1.7)
- - GoogleAPIClientForREST/Vision (1.3.10):
+ - TensorFlowLiteObjC (~> 2.1.0)
+ - GoogleAPIClientForREST/Core (1.7.0):
+ - GTMSessionFetcher (< 2.0, >= 1.6.1)
+ - GoogleAPIClientForREST/Vision (1.7.0):
- GoogleAPIClientForREST/Core
- - GTMSessionFetcher (>= 1.1.7)
- - GoogleDataTransport (1.2.0)
- - GoogleDataTransportCCTSupport (1.0.3):
- - GoogleDataTransport (~> 1.2)
- - nanopb
- - GoogleToolboxForMac/DebugUtils (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - GoogleToolboxForMac/Defines (2.2.1)
- - GoogleToolboxForMac/Logger (2.2.1):
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSData+zlib (2.2.1)":
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSDictionary+URLArguments (2.2.1)":
- - GoogleToolboxForMac/DebugUtils (= 2.2.1)
- - GoogleToolboxForMac/Defines (= 2.2.1)
- - "GoogleToolboxForMac/NSString+URLArguments (= 2.2.1)"
- - "GoogleToolboxForMac/NSString+URLArguments (2.2.1)"
- - GoogleUtilities/Environment (6.2.5)
- - GoogleUtilities/Logger (6.2.5):
+ - GTMSessionFetcher (< 2.0, >= 1.6.1)
+ - GoogleDataTransport (7.5.1):
+ - nanopb (~> 1.30906.0)
+ - GoogleToolboxForMac/DebugUtils (2.3.2):
+ - GoogleToolboxForMac/Defines (= 2.3.2)
+ - GoogleToolboxForMac/Defines (2.3.2)
+ - GoogleToolboxForMac/Logger (2.3.2):
+ - GoogleToolboxForMac/Defines (= 2.3.2)
+ - "GoogleToolboxForMac/NSData+zlib (2.3.2)":
+ - GoogleToolboxForMac/Defines (= 2.3.2)
+ - "GoogleToolboxForMac/NSDictionary+URLArguments (2.3.2)":
+ - GoogleToolboxForMac/DebugUtils (= 2.3.2)
+ - GoogleToolboxForMac/Defines (= 2.3.2)
+ - "GoogleToolboxForMac/NSString+URLArguments (= 2.3.2)"
+ - "GoogleToolboxForMac/NSString+URLArguments (2.3.2)"
+ - GoogleUtilities/Environment (6.7.2):
+ - PromisesObjC (~> 1.2)
+ - GoogleUtilities/Logger (6.7.2):
- GoogleUtilities/Environment
- - GoogleUtilities/UserDefaults (6.2.5):
+ - GoogleUtilities/UserDefaults (6.7.2):
- GoogleUtilities/Logger
- - GTMSessionFetcher (1.2.2):
- - GTMSessionFetcher/Full (= 1.2.2)
- - GTMSessionFetcher/Core (1.2.2)
- - GTMSessionFetcher/Full (1.2.2):
- - GTMSessionFetcher/Core (= 1.2.2)
- - nanopb (0.3.901):
- - nanopb/decode (= 0.3.901)
- - nanopb/encode (= 0.3.901)
- - nanopb/decode (0.3.901)
- - nanopb/encode (0.3.901)
- - Protobuf (3.9.0)
- - TensorFlowLiteC (1.14.0)
- - TensorFlowLiteObjC (1.14.0):
- - TensorFlowLiteC (= 1.14.0)
+ - GTMSessionFetcher (1.7.2):
+ - GTMSessionFetcher/Full (= 1.7.2)
+ - GTMSessionFetcher/Core (1.7.2)
+ - GTMSessionFetcher/Full (1.7.2):
+ - GTMSessionFetcher/Core (= 1.7.2)
+ - nanopb (1.30906.0):
+ - nanopb/decode (= 1.30906.0)
+ - nanopb/encode (= 1.30906.0)
+ - nanopb/decode (1.30906.0)
+ - nanopb/encode (1.30906.0)
+ - PromisesObjC (1.2.12)
+ - Protobuf (3.26.1)
+ - TensorFlowLiteC (2.1.0)
+ - TensorFlowLiteObjC (2.1.0):
+ - TensorFlowLiteC (= 2.1.0)
DEPENDENCIES:
- Firebase/MLVision
- Firebase/MLVisionAutoML
SPEC REPOS:
- https://github.com/cocoapods/specs.git:
+ trunk:
- Firebase
- FirebaseCore
- FirebaseCoreDiagnostics
- - FirebaseCoreDiagnosticsInterop
- - FirebaseInstanceID
+ - FirebaseInstallations
- FirebaseMLCommon
- FirebaseMLVision
- FirebaseMLVisionAutoML
- GoogleAPIClientForREST
- GoogleDataTransport
- - GoogleDataTransportCCTSupport
- GoogleToolboxForMac
- GoogleUtilities
- GTMSessionFetcher
- nanopb
+ - PromisesObjC
- Protobuf
- TensorFlowLiteC
- TensorFlowLiteObjC
SPEC CHECKSUMS:
- Firebase: c35912a5c160193dc423f260dac3f167a1a795ab
- FirebaseCore: 12422a2a2b79ed161b06ccad1edfe650de7a4b34
- FirebaseCoreDiagnostics: 4c04ae09d0ab027c30179828c6bb47764df1bd13
- FirebaseCoreDiagnosticsInterop: 6829da2b8d1fc795ff1bd99df751d3788035d2cb
- FirebaseInstanceID: 88932a31aba5a56cfd3a7541706436c71f7f4598
- FirebaseMLCommon: 45b456098f5d38c0fe023dd6dca3ee0f91256b2d
- FirebaseMLVision: 33745e08da6adc5375c7979b581b3521dc057f74
- FirebaseMLVisionAutoML: 31f0cde3476fea96a3bdf45d5ac87db2358abf29
- GoogleAPIClientForREST: 4acfffd77f1c3c8741b6be9eaed0e603278efbde
- GoogleDataTransport: 8f9897b8e073687f24ca8d3c3a8013dec7d2d1cc
- GoogleDataTransportCCTSupport: 51134d81fca795c60cc247d1cb6af63c3d67b8d8
- GoogleToolboxForMac: b3553629623a3b1bff17f555e736cd5a6d95ad55
- GoogleUtilities: e7dc37039b19df7fe543479d3e4a02ac8d11bb69
- GTMSessionFetcher: 61bb0f61a4cb560030f1222021178008a5727a23
- nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
- Protobuf: 1097ca58584c8d9be81bfbf2c5ff5975648dd87a
- TensorFlowLiteC: a6702011fb661928634e59565b5fe262f69692d0
- TensorFlowLiteObjC: ece71b1e78f3df5952996c1606934b1d5538c875
+ Firebase: c23a36d9e4cdf7877dfcba8dd0c58add66358999
+ FirebaseCore: d3a978a3cfa3240bf7e4ba7d137fdf5b22b628ec
+ FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1
+ FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2
+ FirebaseMLCommon: f42d067ca7fed962e09f02ba94a24e06ee50d933
+ FirebaseMLVision: fd7cdd33d067c976c16fd521e7e92c26c980c947
+ FirebaseMLVisionAutoML: 869af2667c30ac90bd8aefd14e92f8c99b69862b
+ GoogleAPIClientForREST: 2d4140915e2ec6d1bcb39c9df4a534c75706c595
+ GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
+ GoogleToolboxForMac: 8bef7c7c5cf7291c687cf5354f39f9db6399ad34
+ GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
+ GTMSessionFetcher: 5595ec75acf5be50814f81e9189490412bad82ba
+ nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
+ PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
+ Protobuf: a53f5173a603075b3522a5c50be63a67a5f3353a
+ TensorFlowLiteC: 215603d4426d93810eace5947e317389554a4b66
+ TensorFlowLiteObjC: 2e074eb41084037aeda9a8babe111fdd3ac99974
PODFILE CHECKSUM: 4b071879fc5f9391b9325777ac56ce58e70e8b8d
-COCOAPODS: 1.7.5
+COCOAPODS: 1.15.2
diff --git a/mlkit/objc-snippets/AutoMLVision.m b/mlkit/objc-snippets/AutoMLVision.m
index effb048e..49b07e39 100644
--- a/mlkit/objc-snippets/AutoMLVision.m
+++ b/mlkit/objc-snippets/AutoMLVision.m
@@ -15,7 +15,7 @@
//
#import
-@import Firebase;
+@import FirebaseMLVision;
@interface AutoMLVision : NSObject
diff --git a/mlkit/objc-snippets/ImagePreparation.m b/mlkit/objc-snippets/ImagePreparation.m
index 430342fd..421dbb40 100644
--- a/mlkit/objc-snippets/ImagePreparation.m
+++ b/mlkit/objc-snippets/ImagePreparation.m
@@ -16,7 +16,7 @@
#import
@import AVFoundation;
-@import Firebase;
+@import FirebaseMLVision;
@interface ImagePreparation : NSObject
diff --git a/mlkit/swift-snippets/AutoMLVision.swift b/mlkit/swift-snippets/AutoMLVision.swift
index a717a031..64180aa8 100644
--- a/mlkit/swift-snippets/AutoMLVision.swift
+++ b/mlkit/swift-snippets/AutoMLVision.swift
@@ -14,7 +14,7 @@
// limitations under the License.
//
-import Firebase
+import FirebaseMLVision
class AutoMLVision {
func label(image: VisionImage) {
diff --git a/mlkit/swift-snippets/ImagePreparation.swift b/mlkit/swift-snippets/ImagePreparation.swift
index c3819a7e..a4e6bce0 100644
--- a/mlkit/swift-snippets/ImagePreparation.swift
+++ b/mlkit/swift-snippets/ImagePreparation.swift
@@ -17,7 +17,7 @@
import Foundation
import AVFoundation
-import Firebase
+import FirebaseMLVision
class ImagePreparation {
func createImage(uiImage: UIImage) -> VisionImage {
diff --git a/invites/InvitesExample/AppDelegate.h b/qs-snippets/DatabaseExample/AppDelegate.h
similarity index 88%
rename from invites/InvitesExample/AppDelegate.h
rename to qs-snippets/DatabaseExample/AppDelegate.h
index 409c657c..b6060b5c 100644
--- a/invites/InvitesExample/AppDelegate.h
+++ b/qs-snippets/DatabaseExample/AppDelegate.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) Google Inc.
+// Copyright (c) 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,6 +18,6 @@
@interface AppDelegate : UIResponder
-@property(strong, nonatomic) UIWindow *window;
+@property(nonatomic, strong) UIWindow *window;
@end
diff --git a/qs-snippets/DatabaseExample/AppDelegate.m b/qs-snippets/DatabaseExample/AppDelegate.m
new file mode 100644
index 00000000..2643e7d2
--- /dev/null
+++ b/qs-snippets/DatabaseExample/AppDelegate.m
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "AppDelegate.h"
+@import FirebaseCore;
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // [START initialize_firebase]
+ [FIRApp configure];
+ // [END initialize_firebase]
+ return YES;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/Base.lproj/Main.storyboard b/qs-snippets/DatabaseExample/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..af653da9
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Base.lproj/Main.storyboard
@@ -0,0 +1,458 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qs-snippets/DatabaseExample/Comment.h b/qs-snippets/DatabaseExample/Comment.h
new file mode 100644
index 00000000..33582f6b
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Comment.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@interface Comment : NSObject
+@property(strong, nonatomic) NSString *uid;
+@property(strong, nonatomic) NSString *author;
+@property(strong, nonatomic) NSString *text;
+
+- (instancetype)initWithUid:(NSString *)uid
+ andAuthor:(NSString *)author
+ andText:(NSString *)text NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/qs-snippets/DatabaseExample/Comment.m b/qs-snippets/DatabaseExample/Comment.m
new file mode 100644
index 00000000..832c1fa2
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Comment.m
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "Comment.h"
+
+@implementation Comment
+
+- (instancetype)init {
+ return [self initWithUid:@"" andAuthor:@"" andText:@""];
+}
+
+- (instancetype)initWithUid:(NSString *)uid andAuthor:(NSString *)author andText:(NSString *)text {
+ self = [super init];
+ if (self) {
+ self.uid = uid;
+ self.author = author;
+ self.text = text;
+ }
+ return self;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/DatabaseExampleSwift-Bridging-Header.h b/qs-snippets/DatabaseExample/DatabaseExampleSwift-Bridging-Header.h
new file mode 100644
index 00000000..3a24de6f
--- /dev/null
+++ b/qs-snippets/DatabaseExample/DatabaseExampleSwift-Bridging-Header.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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.
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "UIViewController+Alerts.h"
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/Contents.json
new file mode 100644
index 00000000..4bd32cab
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_account_circle.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_account_circle_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_account_circle_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle.png
new file mode 100644
index 00000000..0c1202de
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_2x.png
new file mode 100644
index 00000000..f26b201a
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_3x.png
new file mode 100644
index 00000000..3cc0a63e
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_account_circle.imageset/ic_account_circle_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/Contents.json
new file mode 100644
index 00000000..a065596e
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_history.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_history_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_history_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history.png
new file mode 100644
index 00000000..9fade8bb
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_2x.png
new file mode 100644
index 00000000..f6096cab
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_3x.png
new file mode 100644
index 00000000..f837fda0
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_history.imageset/ic_history_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/Contents.json
new file mode 100644
index 00000000..8328848a
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_person.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_person_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_person_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person.png
new file mode 100644
index 00000000..57da32af
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_2x.png
new file mode 100644
index 00000000..360a32f2
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_3x.png
new file mode 100644
index 00000000..f1e14849
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_person.imageset/ic_person_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/Contents.json
new file mode 100644
index 00000000..4cb52f80
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star.png
new file mode 100644
index 00000000..a728afe6
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_2x.png
new file mode 100644
index 00000000..c636ce8e
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_3x.png
new file mode 100644
index 00000000..54d30659
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star.imageset/ic_star_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/Contents.json
new file mode 100644
index 00000000..fd678197
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star_border.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star_border_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_star_border_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border.png
new file mode 100644
index 00000000..b7538480
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_2x.png
new file mode 100644
index 00000000..4f978e73
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_3x.png
new file mode 100644
index 00000000..f10d4274
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_star_border.imageset/ic_star_border_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/Contents.json b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/Contents.json
new file mode 100644
index 00000000..51bfeed3
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_whatshot.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_whatshot_2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "ic_whatshot_3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot.png
new file mode 100644
index 00000000..31b1981f
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_2x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_2x.png
new file mode 100644
index 00000000..e9ae8267
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_2x.png differ
diff --git a/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_3x.png b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_3x.png
new file mode 100644
index 00000000..a14dcd69
Binary files /dev/null and b/qs-snippets/DatabaseExample/Images.xcassets/ic_whatshot.imageset/ic_whatshot_3x.png differ
diff --git a/qs-snippets/DatabaseExample/Info.plist b/qs-snippets/DatabaseExample/Info.plist
new file mode 100644
index 00000000..30d7c486
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Info.plist
@@ -0,0 +1,51 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIcons
+
+ CFBundleIcons~ipad
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/qs-snippets/DatabaseExample/MyPostsViewController.h b/qs-snippets/DatabaseExample/MyPostsViewController.h
new file mode 100644
index 00000000..e21af88d
--- /dev/null
+++ b/qs-snippets/DatabaseExample/MyPostsViewController.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "PostListViewController.h"
+
+@interface MyPostsViewController : PostListViewController
+@end
diff --git a/qs-snippets/DatabaseExample/MyPostsViewController.m b/qs-snippets/DatabaseExample/MyPostsViewController.m
new file mode 100644
index 00000000..37209cd7
--- /dev/null
+++ b/qs-snippets/DatabaseExample/MyPostsViewController.m
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "MyPostsViewController.h"
+
+@implementation MyPostsViewController
+
+- (FIRDatabaseQuery *) getQuery {
+ return [[self.ref child:@"user-posts"] child:[super getUid]];
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/MyTopPostsViewController.h b/qs-snippets/DatabaseExample/MyTopPostsViewController.h
new file mode 100644
index 00000000..ef84e226
--- /dev/null
+++ b/qs-snippets/DatabaseExample/MyTopPostsViewController.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "MyPostsViewController.h"
+
+@interface MyTopPostsViewController : PostListViewController
+
+@end
diff --git a/qs-snippets/DatabaseExample/MyTopPostsViewController.m b/qs-snippets/DatabaseExample/MyTopPostsViewController.m
new file mode 100644
index 00000000..1dff6b0d
--- /dev/null
+++ b/qs-snippets/DatabaseExample/MyTopPostsViewController.m
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "MyTopPostsViewController.h"
+
+@implementation MyTopPostsViewController
+
+- (FIRDatabaseQuery *) getQuery {
+ // [START my_top_posts_query]
+ // My top posts by number of stars
+ FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
+ child:[super getUid]]
+ queryOrderedByChild:@"starCount"];
+ // [END my_top_posts_query]
+ return myTopPostsQuery;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/NewPostViewController.h b/qs-snippets/DatabaseExample/NewPostViewController.h
new file mode 100644
index 00000000..c2b8957f
--- /dev/null
+++ b/qs-snippets/DatabaseExample/NewPostViewController.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase;
+
+@interface NewPostViewController
+ : UIViewController
+
+@property(strong, nonatomic) FIRDatabaseReference *ref;
+
+@end
diff --git a/qs-snippets/DatabaseExample/NewPostViewController.m b/qs-snippets/DatabaseExample/NewPostViewController.m
new file mode 100644
index 00000000..7134999e
--- /dev/null
+++ b/qs-snippets/DatabaseExample/NewPostViewController.m
@@ -0,0 +1,101 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "NewPostViewController.h"
+#import "User.h"
+#import "Post.h"
+#import "UIViewController+Alerts.h"
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+@interface NewPostViewController ()
+ @property (weak) IBOutlet UITextView *bodyTextView;
+ @property (weak) IBOutlet UITextField *titleTextField;
+@end
+
+@implementation NewPostViewController
+
+#pragma mark - UIViewController lifecycle methods
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // [START create_database_reference]
+ self.ref = [[FIRDatabase database] reference];
+ // [END create_database_reference]
+
+ UIToolbar *doneBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
+ doneBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+ UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
+ target:nil
+ action:nil];
+ UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:@"Post"
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(didTapShare:)];
+ done.tintColor = [UIColor colorWithRed:1.0 green:143.0/255.0 blue:0.0 alpha:1.0];
+ doneBar.items = @[flex, done, flex];
+ [doneBar sizeToFit];
+ _bodyTextView.inputAccessoryView = doneBar;
+ _titleTextField.inputAccessoryView = doneBar;
+}
+
+- (IBAction)didTapShare:(id)sender {
+ if (self.titleTextField.text.length == 0 || self.bodyTextView.text.length == 0) {
+ [self showMessagePrompt:@"Neither title nor body can be empty."];
+ return;
+ }
+ // [START single_value_read]
+ NSString *userID = [FIRAuth auth].currentUser.uid;
+ [[[_ref child:@"users"] child:userID] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
+ // Get user value
+ User *user = [[User alloc] initWithUsername:snapshot.value[@"username"]];
+
+ // [START_EXCLUDE]
+ // Write new post
+ [self writeNewPost:userID
+ username:user.username
+ title:self.titleTextField.text
+ body:self.bodyTextView.text];
+ // Finish this Activity, back to the stream
+ [self.navigationController popViewControllerAnimated:YES];
+ // [END_EXCLUDE]
+ } withCancelBlock:^(NSError * _Nonnull error) {
+ NSLog(@"%@", error.localizedDescription);
+ }];
+ // [END single_value_read]
+}
+
+- (void)writeNewPost:(NSString *)userID username:(NSString *)username title:(NSString *)title body:(NSString *)body {
+ // Create new post at /user-posts/$userid/$postid and at
+ // /posts/$postid simultaneously
+ // [START write_fan_out]
+ NSString *key = [[_ref child:@"posts"] childByAutoId].key;
+ NSDictionary *post = @{@"uid": userID,
+ @"author": username,
+ @"title": title,
+ @"body": body};
+ NSDictionary *childUpdates = @{[@"/posts/" stringByAppendingString:key]: post,
+ [NSString stringWithFormat:@"/user-posts/%@/%@/", userID, key]: post};
+ [_ref updateChildValues:childUpdates];
+ // [END write_fan_out]
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField {
+ [textField resignFirstResponder];
+ return NO;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/Post.h b/qs-snippets/DatabaseExample/Post.h
new file mode 100644
index 00000000..b2f585cc
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Post.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@interface Post : NSObject
+@property(strong, nonatomic) NSString *uid;
+@property(strong, nonatomic) NSString *author;
+@property(strong, nonatomic) NSString *title;
+@property(strong, nonatomic) NSString *body;
+@property(assign, nonatomic) int starCount;
+@property(strong, nonatomic) NSDictionary *stars;
+
+- (instancetype)initWithUid:(NSString *)uid
+ andAuthor:(NSString *)author
+ andTitle:(NSString *)title
+ andBody:(NSString *)body NS_DESIGNATED_INITIALIZER;
+
+@end
diff --git a/qs-snippets/DatabaseExample/Post.m b/qs-snippets/DatabaseExample/Post.m
new file mode 100644
index 00000000..a61e78db
--- /dev/null
+++ b/qs-snippets/DatabaseExample/Post.m
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "Post.h"
+
+@implementation Post
+
+- (instancetype)init {
+ return [self initWithUid:@"" andAuthor:@"" andTitle:@"" andBody:@""];
+}
+
+- (instancetype)initWithUid:(NSString *)uid
+ andAuthor:(NSString *)author
+ andTitle:(NSString *)title
+ andBody:(NSString *)body {
+ self = [super init];
+ if (self) {
+ self.uid = uid;
+ self.author = author;
+ self.title = title;
+ self.body = body;
+ }
+ return self;
+}
+@end
diff --git a/qs-snippets/DatabaseExample/PostDataSource.h b/qs-snippets/DatabaseExample/PostDataSource.h
new file mode 100644
index 00000000..b6ee1b8f
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostDataSource.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@import FirebaseDatabaseUI;
+
+@interface PostDataSource : FUITableViewDataSource
+
+@end
diff --git a/qs-snippets/DatabaseExample/PostDataSource.m b/qs-snippets/DatabaseExample/PostDataSource.m
new file mode 100644
index 00000000..f355a55a
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostDataSource.m
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "PostDataSource.h"
+
+@import FirebaseDatabase;
+
+@implementation PostDataSource
+
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
+ return YES;
+}
+
+- (void)tableView:(UITableView *)tableView
+commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
+forRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (editingStyle == UITableViewCellEditingStyleDelete) {
+ [[self snapshotAtIndex:indexPath.row].ref removeValue];
+ }
+}
+
+- (NSInteger)tableView:(UITableView *)tableView
+ numberOfRowsInSection:(NSInteger)section {
+ if (self.count != 0) {
+ tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
+ tableView.backgroundView = nil;
+ }
+ return self.count;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ UILabel *noDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, tableView.bounds.size.height)];
+ noDataLabel.text = @"No posts yet - why not add one?";
+ noDataLabel.textColor = [UIColor blackColor];
+ noDataLabel.textAlignment = NSTextAlignmentCenter;
+ tableView.backgroundView = noDataLabel;
+ tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+ return 1;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/PostDetailTableViewController.h b/qs-snippets/DatabaseExample/PostDetailTableViewController.h
new file mode 100644
index 00000000..15dd912c
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostDetailTableViewController.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@interface PostDetailTableViewController : UITableViewController
+@property (strong, nonatomic) NSString *postKey;
+@end
diff --git a/qs-snippets/DatabaseExample/PostDetailTableViewController.m b/qs-snippets/DatabaseExample/PostDetailTableViewController.m
new file mode 100644
index 00000000..3cb481aa
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostDetailTableViewController.m
@@ -0,0 +1,185 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "Post.h"
+#import "PostDetailTableViewController.h"
+#import "PostTableViewCell.h"
+
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+static const int kSectionComments = 2;
+static const int kSectionSend = 1;
+static const int kSectionPost = 0;
+
+@interface PostDetailTableViewController ()
+@property (strong, nonatomic) NSMutableArray *comments;
+@property (strong, nonatomic) UITextField *commentField;
+@property (strong, nonatomic) Post *post;
+@property (strong, nonatomic) FIRDatabaseReference *postRef;
+@property (strong, nonatomic) FIRDatabaseReference *commentsRef;
+@end
+
+@implementation PostDetailTableViewController
+
+ FIRDatabaseHandle _refHandle;
+
+// UITextViewDelegate protocol method
+- (BOOL)textFieldShouldReturn:(UITextField *)textField {
+ [textField resignFirstResponder];
+ return YES;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ FIRDatabaseReference *ref = [FIRDatabase database].reference;
+ self.postRef = [[ref child:@"posts"] child:_postKey];
+ self.commentsRef = [[ref child:@"post-comments"] child:_postKey];
+ self.comments = [[NSMutableArray alloc] init];
+ self.post = [[Post alloc] init];
+ UINib *nib = [UINib nibWithNibName:@"PostTableViewCell" bundle:nil];
+ [self.tableView registerNib:nib forCellReuseIdentifier:@"post"];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [self.comments removeAllObjects];
+ // [START child_event_listener]
+ // Listen for new comments in the Firebase database
+ [_commentsRef
+ observeEventType:FIRDataEventTypeChildAdded
+ withBlock:^(FIRDataSnapshot *snapshot) {
+ [self.comments addObject:snapshot];
+ [self.tableView insertRowsAtIndexPaths:@[
+ [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments]
+ ]
+ withRowAnimation:UITableViewRowAnimationAutomatic];
+ }];
+ // Listen for deleted comments in the Firebase database
+ [_commentsRef
+ observeEventType:FIRDataEventTypeChildRemoved
+ withBlock:^(FIRDataSnapshot *snapshot) {
+ int index = [self indexOfMessage:snapshot];
+ [self.comments removeObjectAtIndex:index];
+ [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]]
+ withRowAnimation:UITableViewRowAnimationAutomatic];
+ }];
+ // [END child_event_listener]
+
+ // [START post_value_event_listener]
+ _refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
+ NSDictionary *postDict = snapshot.value;
+ // [START_EXCLUDE]
+ [self.post setValuesForKeysWithDictionary:postDict];
+ [self.tableView reloadData];
+ self.navigationItem.title = self.post.title;
+ // [END_EXCLUDE]
+ }];
+ // [END post_value_event_listener]
+}
+
+- (int) indexOfMessage:(FIRDataSnapshot *)snapshot {
+ int index = 0;
+ for (FIRDataSnapshot *comment in _comments) {
+ if ([snapshot.key isEqualToString:comment.key]) {
+ return index;
+ }
+ ++index;
+ }
+ return -1;
+}
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [self.postRef removeObserverWithHandle:_refHandle];
+ [self.commentsRef removeAllObservers];
+ [[[[FIRDatabase database].reference child:@"users"] child:[FIRAuth auth].currentUser.uid] removeAllObservers];
+}
+
+#pragma mark - Table view data source
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return 3;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ if (section == kSectionPost || section == kSectionSend ) {
+ return 1;
+ } else if (section == kSectionComments) {
+ return _comments.count;
+ }
+ NSAssert(NO, @"Unexpected section");
+ return 0;
+}
+- (IBAction)didTapSend:(UIButton *)sender {
+ [self textFieldShouldReturn:_commentField];
+ _commentField.enabled = NO;
+ sender.enabled = NO;
+ NSString *uid = [FIRAuth auth].currentUser.uid;
+ [[[[FIRDatabase database].reference child:@"users"] child:uid]
+ observeSingleEventOfType:FIRDataEventTypeValue
+ withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
+ NSDictionary *user = snapshot.value;
+ NSString *username = user[@"username"];
+ NSDictionary *comment = @{@"uid": uid,
+ @"author": username,
+ @"text": self.commentField.text};
+ [[self.commentsRef childByAutoId] setValue:comment];
+ self.commentField.text = @"";
+ self.commentField.enabled = YES;
+ sender.enabled = YES;
+ }];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell;
+ if (indexPath.section == kSectionPost) {
+ cell = [tableView dequeueReusableCellWithIdentifier:@"post" forIndexPath: indexPath];
+ PostTableViewCell *postcell = (PostTableViewCell *)cell;
+ postcell.authorLabel.text = _post.author;
+ postcell.postTitle.text = _post.title;
+ postcell.postBody.text = _post.body;
+ NSString *imageName = _post.stars[[self getUid]] ? @"ic_star" : @"ic_star_border";
+ [postcell.starButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+ postcell.numStarsLabel.text = [NSString stringWithFormat:@"%d", _post.starCount];
+ postcell.postKey = _postKey;
+
+ } else if (indexPath.section == kSectionComments) {
+ cell = [tableView dequeueReusableCellWithIdentifier:@"comment" forIndexPath: indexPath];
+ NSDictionary *comment = _comments[indexPath.row].value;
+ cell.textLabel.text = comment[@"author"];
+ cell.detailTextLabel.text = comment[@"text"];
+ } else if (indexPath.section == kSectionSend) {
+ cell = [tableView dequeueReusableCellWithIdentifier:@"send" forIndexPath: indexPath];
+ _commentField = [(UITextField *) cell viewWithTag:7];
+ } else {
+ [NSException raise:NSInternalInconsistencyException format:@"Wrong section %ld", (long)indexPath.section];
+ }
+ return cell;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (indexPath.section == kSectionPost) {
+ return 160;
+ }
+ return 56;
+}
+
+- (NSString *) getUid {
+ return [FIRAuth auth].currentUser.uid;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/PostListViewController.h b/qs-snippets/DatabaseExample/PostListViewController.h
new file mode 100644
index 00000000..f432ef5c
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostListViewController.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+@import FirebaseDatabaseUI;
+@import FirebaseDatabase;
+
+@interface PostListViewController : UIViewController
+// [START define_database_reference]
+@property (strong, nonatomic) FIRDatabaseReference *ref;
+// [END define_database_reference]
+@property (strong, nonatomic) FUITableViewDataSource *dataSource;
+
+@property (weak, nonatomic) IBOutlet UITableView *tableView;
+@property (NS_NONATOMIC_IOSONLY, getter=getUid, readonly, copy) NSString *uid;
+@end
diff --git a/qs-snippets/DatabaseExample/PostListViewController.m b/qs-snippets/DatabaseExample/PostListViewController.m
new file mode 100644
index 00000000..70d4f4c4
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostListViewController.m
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "PostListViewController.h"
+#import "Post.h"
+#import "PostTableViewCell.h"
+#import "PostDataSource.h"
+#import "PostDetailTableViewController.h"
+
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+@implementation PostListViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // [START create_database_reference]
+ self.ref = [[FIRDatabase database] reference];
+ // [END create_database_reference]
+
+ NSString *identifier = @"post";
+ UINib *nib = [UINib nibWithNibName:@"PostTableViewCell" bundle:nil];
+ [self.tableView registerNib:nib forCellReuseIdentifier:identifier];
+
+ self.dataSource = [[PostDataSource alloc] initWithQuery:[self getQuery]
+ populateCell:^UITableViewCell * _Nonnull(UITableView * _Nonnull tableView,
+ NSIndexPath * _Nonnull indexPath,
+ FIRDataSnapshot * _Nonnull snap) {
+ Post *post = [[Post alloc] initWithUid:snap.value[@"uid"]
+ andAuthor:snap.value[@"author"]
+ andTitle:snap.value[@"title"]
+ andBody:snap.value[@"body"]];
+ PostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
+ cell.authorImage.image = [UIImage imageNamed:@"ic_account_circle"];
+ cell.authorLabel.text = post.author;
+ NSString *imageName = post.stars[[self getUid]] ? @"ic_star" : @"ic_star_border";
+ [cell.starButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+ cell.numStarsLabel.text = [NSString stringWithFormat:@"%d", post.starCount];
+ cell.postTitle.text = post.title;
+ cell.postBody.text = post.body;
+ return cell;
+ }];
+
+ [self.dataSource bindToView:self.tableView];
+ self.tableView.delegate = self;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ [self performSegueWithIdentifier:@"detail" sender:indexPath];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [self.tableView reloadData];
+}
+
+-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+ return 150;
+}
+
+- (NSString *) getUid {
+ return [FIRAuth auth].currentUser.uid;
+}
+
+- (FIRDatabaseQuery *) getQuery {
+ return self.ref;
+}
+
+-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ NSIndexPath *indexPath = sender;
+ PostDetailTableViewController *detail = segue.destinationViewController;
+ detail.postKey = [self.dataSource snapshotAtIndex:indexPath.row].key;
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [[self getQuery] removeAllObservers];
+}
+@end
diff --git a/qs-snippets/DatabaseExample/PostTableViewCell.h b/qs-snippets/DatabaseExample/PostTableViewCell.h
new file mode 100644
index 00000000..8f833783
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostTableViewCell.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+@import FirebaseDatabase;
+
+@interface PostTableViewCell : UITableViewCell
+@property (weak, nonatomic) IBOutlet UIImageView *authorImage;
+@property (weak, nonatomic) IBOutlet UILabel *authorLabel;
+@property (weak, nonatomic) IBOutlet UIButton *starButton;
+@property (weak, nonatomic) IBOutlet UILabel *numStarsLabel;
+@property (weak, nonatomic) IBOutlet UILabel *postTitle;
+@property (weak, nonatomic) IBOutlet UITextView *postBody;
+@property (weak, nonatomic) NSString *postKey;
+@end
diff --git a/qs-snippets/DatabaseExample/PostTableViewCell.m b/qs-snippets/DatabaseExample/PostTableViewCell.m
new file mode 100644
index 00000000..834ba0df
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostTableViewCell.m
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "PostTableViewCell.h"
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+@interface PostTableViewCell ()
+ @property (strong, nonatomic) FIRDatabaseReference *postRef;
+@end
+
+@implementation PostTableViewCell
+
+- (IBAction)didTapStarButton:(id)sender {
+ if (!self.postKey) {
+ // We don't know the identifier of this post, so just return.
+ return;
+ }
+ self.postRef = [[[[FIRDatabase database] reference] child:@"posts"] child:self.postKey];
+ [self incrementStarsForRef:self.postRef];
+ [self.postRef observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
+ NSString *uid = snapshot.value[@"uid"];
+ FIRDatabaseReference *ref = [[[[[FIRDatabase database] reference]
+ child:@"user-posts"]
+ child:uid] child:self.postKey];
+ [self incrementStarsForRef:ref];
+ }];
+}
+
+- (void)incrementStarsForRef:(FIRDatabaseReference *)ref {
+ // [START post_stars_transaction]
+ [ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) {
+ NSMutableDictionary *post = currentData.value;
+ if (!post || [post isEqual:[NSNull null]]) {
+ return [FIRTransactionResult successWithValue:currentData];
+ }
+
+ NSMutableDictionary *stars = post[@"stars"];
+ if (!stars) {
+ stars = [[NSMutableDictionary alloc] initWithCapacity:1];
+ }
+ NSString *uid = [FIRAuth auth].currentUser.uid;
+ int starCount = [post[@"starCount"] intValue];
+ if (stars[uid]) {
+ // Unstar the post and remove self from stars
+ starCount--;
+ [stars removeObjectForKey:uid];
+ } else {
+ // Star the post and add self to stars
+ starCount++;
+ stars[uid] = @YES;
+ }
+ post[@"stars"] = stars;
+ post[@"starCount"] = @(starCount);
+
+ // Set value and report transaction success
+ currentData.value = post;
+ return [FIRTransactionResult successWithValue:currentData];
+ } andCompletionBlock:^(NSError * _Nullable error,
+ BOOL committed,
+ FIRDataSnapshot * _Nullable snapshot) {
+ // Transaction completed
+ if (error) {
+ NSLog(@"%@", error.localizedDescription);
+ }
+ }];
+ // [END post_stars_transaction]
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/PostTableViewCell.xib b/qs-snippets/DatabaseExample/PostTableViewCell.xib
new file mode 100644
index 00000000..58274553
--- /dev/null
+++ b/qs-snippets/DatabaseExample/PostTableViewCell.xib
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qs-snippets/DatabaseExample/RecentPostsViewController.h b/qs-snippets/DatabaseExample/RecentPostsViewController.h
new file mode 100644
index 00000000..583c6a36
--- /dev/null
+++ b/qs-snippets/DatabaseExample/RecentPostsViewController.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "PostListViewController.h"
+
+@interface RecentPostsViewController : PostListViewController
+
+@end
diff --git a/qs-snippets/DatabaseExample/RecentPostsViewController.m b/qs-snippets/DatabaseExample/RecentPostsViewController.m
new file mode 100644
index 00000000..690f0acd
--- /dev/null
+++ b/qs-snippets/DatabaseExample/RecentPostsViewController.m
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "RecentPostsViewController.h"
+
+@implementation RecentPostsViewController
+
+- (FIRDatabaseQuery *) getQuery {
+ // [START recent_posts_query]
+ // Last 100 posts, these are automatically the 100 most recent
+ // due to sorting by push() keys
+ FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
+ // [END recent_posts_query]
+ return recentPostsQuery;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/SignInViewController.h b/qs-snippets/DatabaseExample/SignInViewController.h
new file mode 100644
index 00000000..30f61d29
--- /dev/null
+++ b/qs-snippets/DatabaseExample/SignInViewController.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+@import FirebaseDatabase;
+
+@interface SignInViewController : UIViewController
+@property (strong, nonatomic) FIRDatabaseReference *ref;
+@end
diff --git a/qs-snippets/DatabaseExample/SignInViewController.m b/qs-snippets/DatabaseExample/SignInViewController.m
new file mode 100644
index 00000000..e1db6d30
--- /dev/null
+++ b/qs-snippets/DatabaseExample/SignInViewController.m
@@ -0,0 +1,149 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "SignInViewController.h"
+#import "UIViewController+Alerts.h"
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+@interface SignInViewController ()
+@property (weak, nonatomic) IBOutlet UITextField *emailField;
+@property (weak, nonatomic) IBOutlet UITextField *passwordField;
+@end
+
+@implementation SignInViewController
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ [self.view endEditing:YES];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ if ([FIRAuth auth].currentUser) {
+ [self performSegueWithIdentifier:@"signIn" sender:nil];
+ }
+ _ref = [[FIRDatabase database] reference];
+}
+
+- (IBAction)didTapEmailLogin:(id)sender {
+ [self showSpinner:^{
+ [[FIRAuth auth] signInWithEmail:self.emailField.text
+ password:self.passwordField.text
+ completion:^(FIRAuthDataResult * _Nullable authResult, NSError *error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ [[[self.ref child:@"users"] child:authResult.user.uid]
+ observeEventType:FIRDataEventTypeValue
+ withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
+ if (![snapshot exists]) {
+ [self promptForNewUserName:authResult.user];
+ } else {
+ [self performSegueWithIdentifier:@"signIn"
+ sender:nil];
+ }
+ }];
+ }];
+ }];
+ }];
+}
+
+- (void)promptForNewUserName:(FIRUser *)user {
+ [self showTextInputPromptWithMessage:@"Username:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable username) {
+ if (!userPressedOK || !username.length) {
+ return;
+ }
+ [self showSpinner:^{
+ FIRUserProfileChangeRequest *changeRequest =[user profileChangeRequest];
+ changeRequest.displayName = username;
+ [changeRequest commitChangesWithCompletion:^(NSError *_Nullable error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ [[[self.ref child:@"users"] child:[FIRAuth auth].currentUser.uid]
+ setValue:@{@"username": username}];
+ [self performSegueWithIdentifier:@"signIn" sender:nil];
+ }];
+ }];
+ }];
+ }];
+
+}
+
+- (IBAction)didTapSignUp:(id)sender {
+ [self showTextInputPromptWithMessage:@"Email:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
+ if (!userPressedOK || !email.length) {
+ return;
+ }
+ [self showTextInputPromptWithMessage:@"Password:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable password) {
+ if (!userPressedOK || !password.length) {
+ return;
+ }
+ [self showTextInputPromptWithMessage:@"Username:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable username) {
+ if (!userPressedOK || !username.length) {
+ return;
+ }
+ [self showSpinner:^{
+ [[FIRAuth auth] createUserWithEmail:email password:password
+ completion:^(FIRAuthDataResult * _Nullable authResult,
+ NSError * _Nullable error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ }];
+ [self showSpinner:^{
+ FIRUserProfileChangeRequest *changeRequest =
+ [[FIRAuth auth].currentUser profileChangeRequest];
+ changeRequest.displayName = username;
+ [changeRequest commitChangesWithCompletion:^(NSError *_Nullable error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ // [START basic_write]
+ [[[self.ref child:@"users"] child:authResult.user.uid]
+ setValue:@{@"username": username}];
+ // [END basic_write]
+ [self performSegueWithIdentifier:@"signIn" sender:nil];
+ }];
+ }];
+ }];
+ }];
+ }];
+ }];
+ }];
+ }];
+}
+
+
+#pragma mark - UITextFieldDelegate protocol methods
+- (BOOL)textFieldShouldReturn:(UITextField *)textField {
+ [self didTapEmailLogin:nil];
+ return YES;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/TabBarController.h b/qs-snippets/DatabaseExample/TabBarController.h
new file mode 100644
index 00000000..01893bda
--- /dev/null
+++ b/qs-snippets/DatabaseExample/TabBarController.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@interface TabBarController : UITabBarController
+
+@end
diff --git a/qs-snippets/DatabaseExample/TabBarController.m b/qs-snippets/DatabaseExample/TabBarController.m
new file mode 100644
index 00000000..ba4847e6
--- /dev/null
+++ b/qs-snippets/DatabaseExample/TabBarController.m
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "TabBarController.h"
+@import FirebaseDatabase;
+@import FirebaseAuth;
+
+
+@implementation TabBarController
+
+
+- (void)didMoveToParentViewController:(UIViewController *)parent {
+ if (parent == nil) {
+ NSError *signOutError;
+ BOOL status = [[FIRAuth auth] signOut:&signOutError];
+ if (!status) {
+ NSLog(@"Error signing out: %@", signOutError);
+ return;
+ }
+ }
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/UIViewController+Alerts.h b/qs-snippets/DatabaseExample/UIViewController+Alerts.h
new file mode 100644
index 00000000..843b9533
--- /dev/null
+++ b/qs-snippets/DatabaseExample/UIViewController+Alerts.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2016 Google Inc.
+//
+// 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
+
+NS_ASSUME_NONNULL_BEGIN
+
+/*! @typedef AlertPromptCompletionBlock
+ @brief The type of callback used to report text input prompt results.
+ */
+typedef void (^AlertPromptCompletionBlock)(BOOL userPressedOK, NSString *_Nullable userInput);
+
+/*! @class Alerts
+ @brief Wrapper for @c UIAlertController and @c UIAlertView for backwards compatability with
+ iOS 6+.
+ */
+@interface UIViewController (Alerts)
+
+/*! @fn showMessagePrompt:
+ @brief Displays an alert with an 'OK' button and a message.
+ @param message The message to display.
+ */
+- (void)showMessagePrompt:(NSString *)message;
+
+/*! @fn showTextInputPromptWithMessage:completionBlock:
+ @brief Shows a prompt with a text field and 'OK'/'Cancel' buttons.
+ @param message The message to display.
+ @param completion A block to call when the user taps 'OK' or 'Cancel'.
+ */
+- (void)showTextInputPromptWithMessage:(NSString *)message
+ completionBlock:(AlertPromptCompletionBlock)completion;
+
+/*! @fn showSpinner
+ @brief Shows the please wait spinner.
+ @param completion Called after the spinner has been hidden.
+ */
+- (void)showSpinner:(nullable void(^)(void))completion;
+
+/*! @fn hideSpinner
+ @brief Hides the please wait spinner.
+ @param completion Called after the spinner has been hidden.
+ */
+- (void)hideSpinner:(nullable void(^)(void))completion;
+
+@end
+
+NS_ASSUME_NONNULL_END
\ No newline at end of file
diff --git a/qs-snippets/DatabaseExample/UIViewController+Alerts.m b/qs-snippets/DatabaseExample/UIViewController+Alerts.m
new file mode 100644
index 00000000..783086c6
--- /dev/null
+++ b/qs-snippets/DatabaseExample/UIViewController+Alerts.m
@@ -0,0 +1,283 @@
+//
+// Copyright (c) 2016 Google Inc.
+//
+// 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 "UIViewController+Alerts.h"
+
+#import
+
+/*! @var kPleaseWaitAssociatedObjectKey
+ @brief Key used to identify the "please wait" spinner associated object.
+ */
+static NSString *const kPleaseWaitAssociatedObjectKey =
+@"_UIViewControllerAlertCategory_PleaseWaitScreenAssociatedObject";
+
+/*! @var kOK
+ @brief Text for an 'OK' button.
+ */
+static NSString *const kOK = @"OK";
+
+/*! @var kCancel
+ @brief Text for an 'Cancel' button.
+ */
+static NSString *const kCancel = @"Cancel";
+
+/*! @class SimpleTextPromptDelegate
+ @brief A @c UIAlertViewDelegate which allows @c UIAlertView to be used with blocks more easily.
+ */
+@interface SimpleTextPromptDelegate : NSObject
+
+/*! @fn init
+ @brief Please use initWithCompletionHandler.
+ */
+- (nullable instancetype)init NS_UNAVAILABLE;
+
+/*! @fn initWithCompletionHandler:
+ @brief Designated initializer.
+ @param completionHandler The block to call when the alert view is dismissed.
+ */
+- (nullable instancetype)initWithCompletionHandler:(AlertPromptCompletionBlock)completionHandler
+NS_DESIGNATED_INITIALIZER;
+
+@end
+
+@implementation UIViewController (Alerts)
+
+/*! @fn supportsAlertController
+ @brief Determines if the current platform supports @c UIAlertController.
+ @return YES if the current platform supports @c UIAlertController.
+ */
+- (BOOL)supportsAlertController {
+ return NSClassFromString(@"UIAlertController") != nil;
+}
+
+- (void)showMessagePrompt:(NSString *)message {
+ if ([self supportsAlertController]) {
+ UIAlertController *alert =
+ [UIAlertController alertControllerWithTitle:nil
+ message:message
+ preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertAction *okAction =
+ [UIAlertAction actionWithTitle:kOK style:UIAlertActionStyleDefault handler:nil];
+ [alert addAction:okAction];
+ [self presentViewController:alert animated:YES completion:nil];
+ } else {
+ UIAlertView *alert =
+ [[UIAlertView alloc] initWithTitle:nil
+ message:message
+ delegate:nil
+ cancelButtonTitle:nil
+ otherButtonTitles:kOK, nil];
+ [alert show];
+ }
+}
+
+- (void)showTextInputPromptWithMessage:(NSString *)message
+ completionBlock:(AlertPromptCompletionBlock)completion {
+ if ([self supportsAlertController]) {
+ UIAlertController *prompt =
+ [UIAlertController alertControllerWithTitle:nil
+ message:message
+ preferredStyle:UIAlertControllerStyleAlert];
+ __weak UIAlertController *weakPrompt = prompt;
+ UIAlertAction *cancelAction =
+ [UIAlertAction actionWithTitle:kCancel
+ style:UIAlertActionStyleCancel
+ handler:^(UIAlertAction * _Nonnull action) {
+ completion(NO, nil);
+ }];
+ UIAlertAction *okAction = [UIAlertAction actionWithTitle:kOK
+ style:UIAlertActionStyleDefault
+ handler:^(UIAlertAction * _Nonnull action) {
+ UIAlertController *strongPrompt = weakPrompt;
+ completion(YES, strongPrompt.textFields[0].text);
+ }];
+ [prompt addTextFieldWithConfigurationHandler:nil];
+ [prompt addAction:cancelAction];
+ [prompt addAction:okAction];
+ [self presentViewController:prompt animated:YES completion:nil];
+ } else {
+ SimpleTextPromptDelegate *prompt =
+ [[SimpleTextPromptDelegate alloc] initWithCompletionHandler:completion];
+ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
+ message:message
+ delegate:prompt
+ cancelButtonTitle:@"Cancel"
+ otherButtonTitles:@"Ok", nil];
+ alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
+ [alertView show];
+ }
+}
+
+- (void)showSpinner:(nullable void(^)(void))completion {
+ if ([self supportsAlertController]) {
+ [self showModernSpinner:completion];
+ } else {
+ [self showIOS7Spinner:completion];
+ }
+}
+
+- (void)showModernSpinner:(nullable void (^)(void))completion {
+ UIAlertController *pleaseWaitAlert =
+ objc_getAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey));
+ if (pleaseWaitAlert) {
+ if (completion) {
+ completion();
+ }
+ return;
+ }
+ pleaseWaitAlert = [UIAlertController alertControllerWithTitle:nil
+ message:@"Please Wait...\n\n\n\n"
+ preferredStyle:UIAlertControllerStyleAlert];
+
+ UIActivityIndicatorView *spinner =
+ [[UIActivityIndicatorView alloc]
+ initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
+ spinner.color = [UIColor blackColor];
+ spinner.center = CGPointMake(pleaseWaitAlert.view.bounds.size.width / 2,
+ pleaseWaitAlert.view.bounds.size.height / 2);
+ spinner.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin |
+ UIViewAutoresizingFlexibleTopMargin |
+ UIViewAutoresizingFlexibleLeftMargin |
+ UIViewAutoresizingFlexibleRightMargin;
+ [spinner startAnimating];
+ [pleaseWaitAlert.view addSubview:spinner];
+
+ objc_setAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey),
+ pleaseWaitAlert,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self presentViewController:pleaseWaitAlert animated:YES completion:completion];
+}
+
+- (void)showIOS7Spinner:(nullable void (^)(void))completion {
+ UIWindow *pleaseWaitWindow =
+ objc_getAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey));
+
+ if (pleaseWaitWindow) {
+ if (completion) {
+ completion();
+ }
+ return;
+ }
+
+ pleaseWaitWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+ pleaseWaitWindow.backgroundColor = [UIColor clearColor];
+ pleaseWaitWindow.windowLevel = UIWindowLevelStatusBar - 1;
+
+ UIView *pleaseWaitView = [[UIView alloc] initWithFrame:pleaseWaitWindow.bounds];
+ pleaseWaitView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
+ UIViewAutoresizingFlexibleHeight;
+ pleaseWaitView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
+ UIActivityIndicatorView *spinner =
+ [[UIActivityIndicatorView alloc]
+ initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
+ spinner.center = pleaseWaitView.center;
+ [pleaseWaitView addSubview:spinner];
+ [spinner startAnimating];
+
+ pleaseWaitView.layer.opacity = 0.0;
+ [self.view addSubview:pleaseWaitView];
+
+ [pleaseWaitWindow addSubview:pleaseWaitView];
+
+ [pleaseWaitWindow makeKeyAndVisible];
+
+ objc_setAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey),
+ pleaseWaitWindow,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+
+ [UIView animateWithDuration:0.5f animations:^{
+ pleaseWaitView.layer.opacity = 1.0f;
+ } completion:^(BOOL finished) {
+ if (completion) {
+ completion();
+ }
+ }];
+}
+
+- (void)hideSpinner:(nullable void(^)(void))completion {
+ if ([self supportsAlertController]) {
+ [self hideModernSpinner:completion];
+ } else {
+ [self hideIOS7Spinner:completion];
+ }
+}
+
+- (void)hideModernSpinner:(nullable void(^)(void))completion {
+ UIAlertController *pleaseWaitAlert =
+ objc_getAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey));
+
+ [pleaseWaitAlert dismissViewControllerAnimated:YES completion:completion];
+
+ objc_setAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey),
+ nil,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)hideIOS7Spinner:(nullable void(^)(void))completion {
+ UIWindow *pleaseWaitWindow =
+ objc_getAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey));
+
+ UIView *pleaseWaitView;
+ pleaseWaitView = pleaseWaitWindow.subviews.firstObject;
+
+ [UIView animateWithDuration:0.5f animations:^{
+ pleaseWaitView.layer.opacity = 0.0f;
+ } completion:^(BOOL finished) {
+ [pleaseWaitWindow resignKeyWindow];
+ objc_setAssociatedObject(self,
+ (__bridge const void *)(kPleaseWaitAssociatedObjectKey),
+ nil,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ if (completion) {
+ completion();
+ }
+ }];
+}
+
+@end
+
+@implementation SimpleTextPromptDelegate {
+ AlertPromptCompletionBlock _completionHandler;
+ SimpleTextPromptDelegate *_retainedSelf;
+}
+
+- (instancetype)initWithCompletionHandler:(AlertPromptCompletionBlock)completionHandler {
+ self = [super init];
+ if (self) {
+ _completionHandler = completionHandler;
+ _retainedSelf = self;
+ }
+ return self;
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
+ if (buttonIndex == alertView.firstOtherButtonIndex) {
+ _completionHandler(YES, [alertView textFieldAtIndex:0].text);
+ } else {
+ _completionHandler(NO, nil);
+ }
+ _completionHandler = nil;
+ _retainedSelf = nil;
+}
+
+@end
diff --git a/qs-snippets/DatabaseExample/User.h b/qs-snippets/DatabaseExample/User.h
new file mode 100644
index 00000000..4872357c
--- /dev/null
+++ b/qs-snippets/DatabaseExample/User.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+@interface User : NSObject
+@property(strong, nonatomic) NSString *username;
+
+- (instancetype)initWithUsername:(NSString *)username NS_DESIGNATED_INITIALIZER;
+
+@end
diff --git a/qs-snippets/DatabaseExample/User.m b/qs-snippets/DatabaseExample/User.m
new file mode 100644
index 00000000..10758ef1
--- /dev/null
+++ b/qs-snippets/DatabaseExample/User.m
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 "User.h"
+
+@implementation User
+
+- (instancetype)init {
+ return [self initWithUsername:@""];
+}
+
+- (instancetype)initWithUsername:(NSString *)username {
+ self = [super init];
+ if (self) {
+ self.username = username;
+ }
+ return self;
+}
+
+@end
diff --git a/invites/InvitesExample/main.m b/qs-snippets/DatabaseExample/main.m
similarity index 100%
rename from invites/InvitesExample/main.m
rename to qs-snippets/DatabaseExample/main.m
diff --git a/qs-snippets/DatabaseExampleSwift/AppDelegate.swift b/qs-snippets/DatabaseExampleSwift/AppDelegate.swift
new file mode 100644
index 00000000..c3e96a60
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/AppDelegate.swift
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseCore
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ var window: UIWindow?
+
+ func application(_ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication
+ .LaunchOptionsKey: Any]?) -> Bool {
+ // [START initialize_firebase]
+ FirebaseApp.configure()
+ // [END initialize_firebase]
+ return true
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/Comment.swift b/qs-snippets/DatabaseExampleSwift/Comment.swift
new file mode 100644
index 00000000..6e0f3b77
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/Comment.swift
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+class Comment: NSObject {
+ var uid: String
+ var author: String
+ var text: String
+
+ init(uid: String, author: String, text: String) {
+ self.uid = uid
+ self.author = author
+ self.text = text
+ }
+
+ override convenience init() {
+ self.init(uid: "", author: "", text: "")
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/MyPostsViewController.swift b/qs-snippets/DatabaseExampleSwift/MyPostsViewController.swift
new file mode 100644
index 00000000..8a683a97
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/MyPostsViewController.swift
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+
+@objc(MyPostsViewController)
+class MyPostsViewController: PostListViewController {
+ override func getQuery() -> DatabaseQuery {
+ return (ref?.child("user-posts").child(getUid()))!
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/MyTopPostsViewController.swift b/qs-snippets/DatabaseExampleSwift/MyTopPostsViewController.swift
new file mode 100644
index 00000000..6e8475b5
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/MyTopPostsViewController.swift
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+
+@objc(MyTopPostsViewController)
+class MyTopPostsViewController: PostListViewController {
+ override func getQuery() -> DatabaseQuery {
+ // [START my_top_posts_query]
+ // My top posts by number of stars
+ let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
+ // [END my_top_posts_query]
+ return myTopPostsQuery
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/NewPostViewController.swift b/qs-snippets/DatabaseExampleSwift/NewPostViewController.swift
new file mode 100644
index 00000000..27db38b7
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/NewPostViewController.swift
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseAuth
+
+@objc(NewPostViewController)
+class NewPostViewController: UIViewController, UITextFieldDelegate {
+ var ref: DatabaseReference!
+ @IBOutlet var bodyTextView: UITextView!
+ @IBOutlet var titleTextField: UITextField!
+
+ // UIView lifecycle methods
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ // [START create_database_reference]
+ ref = Database.database().reference()
+ // [END create_database_reference]
+
+ let doneBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 44))
+ doneBar.autoresizingMask = .flexibleWidth
+ let flex = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
+ let done = UIBarButtonItem(
+ title: "Post",
+ style: .plain,
+ target: self,
+ action: #selector(didTapShare)
+ )
+ done.tintColor = UIColor(red: 1.0, green: 143.0 / 255.0, blue: 0.0, alpha: 1.0)
+ doneBar.items = [flex, done, flex]
+ doneBar.sizeToFit()
+ bodyTextView.inputAccessoryView = doneBar
+ titleTextField.inputAccessoryView = doneBar
+ }
+
+ @IBAction func didTapShare(_ sender: AnyObject) {
+ guard titleTextField.hasText, bodyTextView.hasText else {
+ let alert = UIAlertController(
+ title: nil,
+ message: "Neither title nor body can be empty.",
+ preferredStyle: .alert
+ )
+ alert.addAction(UIAlertAction(title: "OK", style: .default))
+ present(alert, animated: true, completion: nil)
+ return
+ }
+ // [START single_value_read]
+ let userID = Auth.auth().currentUser?.uid
+ ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { snapshot in
+ // Get user value
+ let value = snapshot.value as? NSDictionary
+ let username = value?["username"] as? String ?? ""
+ let user = User(username: username)
+
+ // [START_EXCLUDE]
+ // Write new post
+ self.writeNewPost(
+ withUserID: userID!,
+ username: user.username,
+ title: self.titleTextField.text!,
+ body: self.bodyTextView.text
+ )
+ // Finish this Activity, back to the stream
+ _ = self.navigationController?.popViewController(animated: true)
+ // [END_EXCLUDE]
+ }) { error in
+ print(error.localizedDescription)
+ }
+ // [END single_value_read]
+ }
+
+ func writeNewPost(withUserID userID: String, username: String, title: String, body: String) {
+ // Create new post at /user-posts/$userid/$postid and at
+ // /posts/$postid simultaneously
+ // [START write_fan_out]
+ guard let key = ref.child("posts").childByAutoId().key else { return }
+ let post = ["uid": userID,
+ "author": username,
+ "title": title,
+ "body": body]
+ let childUpdates = ["/posts/\(key)": post,
+ "/user-posts/\(userID)/\(key)/": post]
+ ref.updateChildValues(childUpdates)
+ // [END write_fan_out]
+ }
+
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+ textField.resignFirstResponder()
+ return false
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/Post.swift b/qs-snippets/DatabaseExampleSwift/Post.swift
new file mode 100644
index 00000000..57686e41
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/Post.swift
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+
+class Post: NSObject {
+ var uid: String
+ var author: String
+ var title: String
+ var body: String
+ var starCount: AnyObject?
+ var stars: [String: Bool]?
+
+ init(uid: String, author: String, title: String, body: String) {
+ self.uid = uid
+ self.author = author
+ self.title = title
+ self.body = body
+ starCount = 0 as AnyObject?
+ }
+
+ init?(snapshot: DataSnapshot) {
+ guard let dict = snapshot.value as? [String: Any] else { return nil }
+ guard let uid = dict["uid"] as? String else { return nil }
+ guard let author = dict["author"] as? String else { return nil }
+ guard let title = dict["title"] as? String else { return nil }
+ guard let body = dict["body"] as? String else { return nil }
+ let starCount = dict["starCount"] as? Int ?? 0
+
+ self.uid = uid
+ self.author = author
+ self.title = title
+ self.body = body
+ self.starCount = starCount as AnyObject?
+ }
+
+ override convenience init() {
+ self.init(uid: "", author: "", title: "", body: "")
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/PostDataSource.swift b/qs-snippets/DatabaseExampleSwift/PostDataSource.swift
new file mode 100644
index 00000000..61397be1
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/PostDataSource.swift
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabaseUI
+
+class PostDataSource: FUITableViewDataSource {
+ override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
+ return true
+ }
+
+ override func tableView(_ tableView: UITableView,
+ commit editingStyle: UITableViewCell.EditingStyle,
+ forRowAt indexPath: IndexPath) {
+ if editingStyle == .delete {
+ snapshot(at: indexPath.row).ref.removeValue()
+ }
+ }
+
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ if count != 0 {
+ tableView.separatorStyle = .singleLine
+ tableView.backgroundView = nil
+ }
+ return Int(count)
+ }
+
+ override func numberOfSections(in tableView: UITableView) -> Int {
+ let noDataLabel = UILabel(frame: CGRect(origin: .zero, size: tableView.bounds.size))
+ noDataLabel.text = "No posts yet - why not add one?"
+ noDataLabel.textColor = UIColor.black
+ noDataLabel.textAlignment = .center
+ tableView.backgroundView = noDataLabel
+ tableView.separatorStyle = .none
+ return 1
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/PostDetailTableViewController.swift b/qs-snippets/DatabaseExampleSwift/PostDetailTableViewController.swift
new file mode 100644
index 00000000..182faf3f
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/PostDetailTableViewController.swift
@@ -0,0 +1,190 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseAuth
+
+@objc(PostDetailTableViewController)
+class PostDetailTableViewController: UITableViewController, UITextFieldDelegate {
+ let kSectionComments = 2
+ let kSectionSend = 1
+ let kSectionPost = 0
+
+ var postKey = ""
+ var comments: [DataSnapshot] = []
+ var commentField: UITextField?
+ var post: Post = Post()
+ lazy var ref: DatabaseReference = Database.database().reference()
+ var postRef: DatabaseReference!
+ var commentsRef: DatabaseReference!
+ var refHandle: DatabaseHandle?
+
+ // UITextViewDelegate protocol method
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+ textField.resignFirstResponder()
+ return true
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ postRef = ref.child("posts").child(postKey)
+ commentsRef = ref.child("post-comments").child(postKey)
+ let nib = UINib(nibName: "PostTableViewCell", bundle: nil)
+ tableView.register(nib, forCellReuseIdentifier: "post")
+ }
+
+ override func viewWillAppear(_ animated: Bool) {
+ super.viewWillAppear(animated)
+ comments.removeAll()
+ // [START child_event_listener]
+ // Listen for new comments in the Firebase database
+ commentsRef.observe(.childAdded, with: { (snapshot) -> Void in
+ self.comments.append(snapshot)
+ self.tableView.insertRows(
+ at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)],
+ with: UITableView.RowAnimation.automatic
+ )
+ })
+ // Listen for deleted comments in the Firebase database
+ commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in
+ let index = self.indexOfMessage(snapshot)
+ self.comments.remove(at: index)
+ self.tableView.deleteRows(
+ at: [IndexPath(row: index, section: self.kSectionComments)],
+ with: UITableView.RowAnimation.automatic
+ )
+ })
+ // [END child_event_listener]
+
+ // [START post_value_event_listener]
+ refHandle = postRef.observe(DataEventType.value, with: { snapshot in
+ // [START_EXCLUDE]
+ if let post = Post(snapshot: snapshot) {
+ self.post = post
+ }
+ self.tableView.reloadData()
+ self.navigationItem.title = self.post.title
+ // [END_EXCLUDE]
+ })
+ // [END post_value_event_listener]
+ }
+
+ func indexOfMessage(_ snapshot: DataSnapshot) -> Int {
+ var index = 0
+ for comment in comments {
+ if snapshot.key == comment.key {
+ return index
+ }
+ index += 1
+ }
+ return -1
+ }
+
+ override func viewWillDisappear(_ animated: Bool) {
+ super.viewWillDisappear(animated)
+ if let refHandle = refHandle {
+ postRef.removeObserver(withHandle: refHandle)
+ }
+ commentsRef.removeAllObservers()
+ if let uid = Auth.auth().currentUser?.uid {
+ Database.database().reference().child("users").child(uid).removeAllObservers()
+ }
+ }
+
+ // UITableViewDataSource protocol methods
+ override func numberOfSections(in tableView: UITableView) -> Int {
+ return 3
+ }
+
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ switch section {
+ case kSectionPost, kSectionSend:
+ return 1
+ case kSectionComments:
+ return comments.count
+ default:
+ return 0
+ }
+ }
+
+ @IBAction func didTapSend(_ sender: UIButton) {
+ _ = textFieldShouldReturn(commentField!)
+ commentField?.isEnabled = false
+ sender.isEnabled = false
+ if let uid = Auth.auth().currentUser?.uid {
+ Database.database().reference().child("users").child(uid)
+ .observeSingleEvent(of: .value, with: { snapshot in
+ if let commentField = self.commentField,
+ let user = snapshot.value as? [String: AnyObject] {
+ let comment = [
+ "uid": uid,
+ "author": user["username"] as? String ?? "",
+ "text": commentField.text!,
+ ]
+ self.commentsRef.childByAutoId().setValue(comment)
+ commentField.text = ""
+ commentField.isEnabled = true
+ sender.isEnabled = true
+ }
+ })
+ }
+ }
+
+ override func tableView(_ tableView: UITableView,
+ cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell: UITableViewCell
+
+ switch indexPath.section {
+ case kSectionPost:
+ cell = tableView.dequeueReusableCell(withIdentifier: "post", for: indexPath)
+ if let uid = Auth.auth().currentUser?.uid {
+ guard let postcell = cell as? PostTableViewCell else {
+ break
+ }
+ let imageName = post.stars == nil || post.stars![uid] == nil ? "ic_star_border" : "ic_star"
+ postcell.authorLabel.text = post.author
+ postcell.postTitle.text = post.title
+ postcell.postBody.text = post.body
+ postcell.starButton.setImage(UIImage(named: imageName), for: .normal)
+ if let starCount = post.starCount {
+ postcell.numStarsLabel.text = "\(starCount)"
+ }
+ postcell.postKey = postKey
+ }
+ case kSectionComments:
+ cell = tableView.dequeueReusableCell(withIdentifier: "comment", for: indexPath)
+ let commentDict = comments[indexPath.row].value as? [String: AnyObject]
+ if let text = cell.textLabel, let detail = cell.detailTextLabel,
+ let author = commentDict?["author"], let commentText = commentDict?["text"] {
+ detail.text = String(describing: author)
+ text.text = String(describing: commentText)
+ }
+ default: // kSectionSend
+ cell = tableView.dequeueReusableCell(withIdentifier: "send", for: indexPath)
+ commentField = cell.viewWithTag(7) as? UITextField
+ }
+ return cell
+ }
+
+ override func tableView(_ tableView: UITableView,
+ heightForRowAt indexPath: IndexPath) -> CGFloat {
+ if indexPath.section == kSectionPost {
+ return 160
+ }
+ return 56
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/PostListViewController.swift b/qs-snippets/DatabaseExampleSwift/PostListViewController.swift
new file mode 100644
index 00000000..89815480
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/PostListViewController.swift
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseDatabaseUI
+import FirebaseAuth
+
+@objc(PostListViewController)
+class PostListViewController: UIViewController, UITableViewDelegate {
+ // [START define_database_reference]
+ var ref: DatabaseReference!
+ // [END define_database_reference]
+
+ var dataSource: FUITableViewDataSource?
+
+ @IBOutlet var tableView: UITableView!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ // [START create_database_reference]
+ ref = Database.database().reference()
+ // [END create_database_reference]
+
+ let identifier = "post"
+ let nib = UINib(nibName: "PostTableViewCell", bundle: nil)
+ tableView.register(nib, forCellReuseIdentifier: identifier)
+
+ dataSource =
+ FUITableViewDataSource(query: getQuery()) { (tableView, indexPath, snap) -> UITableViewCell in
+ let cell = tableView.dequeueReusableCell(
+ withIdentifier: identifier,
+ for: indexPath
+ ) as! PostTableViewCell
+
+ guard let post = Post(snapshot: snap) else { return cell }
+ cell.authorImage.image = UIImage(named: "ic_account_circle")
+ cell.authorLabel.text = post.author
+ var imageName = "ic_star_border"
+ if (post.stars?[self.getUid()]) != nil {
+ imageName = "ic_star"
+ }
+ cell.starButton.setImage(UIImage(named: imageName), for: .normal)
+ if let starCount = post.starCount {
+ cell.numStarsLabel.text = "\(starCount)"
+ }
+ cell.postTitle.text = post.title
+ cell.postBody.text = post.body
+ return cell
+ }
+
+ dataSource?.bind(to: tableView)
+ tableView.delegate = self
+ }
+
+ override func viewWillAppear(_ animated: Bool) {
+ super.viewWillAppear(animated)
+ tableView.reloadData()
+ }
+
+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+ performSegue(withIdentifier: "detail", sender: indexPath)
+ }
+
+ func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+ return 150
+ }
+
+ func getUid() -> String {
+ return (Auth.auth().currentUser?.uid)!
+ }
+
+ func getQuery() -> DatabaseQuery {
+ return ref
+ }
+
+ override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+ guard let indexPath: IndexPath = sender as? IndexPath else { return }
+ guard let detail: PostDetailTableViewController = segue
+ .destination as? PostDetailTableViewController else {
+ return
+ }
+ if let dataSource = dataSource {
+ detail.postKey = dataSource.snapshot(at: indexPath.row).key
+ }
+ }
+
+ override func viewWillDisappear(_ animated: Bool) {
+ super.viewWillDisappear(animated)
+ getQuery().removeAllObservers()
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/PostTableViewCell.swift b/qs-snippets/DatabaseExampleSwift/PostTableViewCell.swift
new file mode 100644
index 00000000..998f617d
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/PostTableViewCell.swift
@@ -0,0 +1,82 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseAuth
+
+@objc(PostTableViewCell)
+class PostTableViewCell: UITableViewCell {
+ @IBOutlet var authorImage: UIImageView!
+ @IBOutlet var authorLabel: UILabel!
+ @IBOutlet var starButton: UIButton!
+ @IBOutlet var numStarsLabel: UILabel!
+ @IBOutlet var postTitle: UILabel!
+ @IBOutlet var postBody: UITextView!
+ var postKey: String?
+ var postRef: DatabaseReference!
+
+ @IBAction func didTapStarButton(_ sender: AnyObject) {
+ if let postKey = postKey {
+ postRef = Database.database().reference().child("posts").child(postKey)
+ incrementStars(forRef: postRef)
+ postRef.observeSingleEvent(of: .value, with: { snapshot in
+ let value = snapshot.value as? NSDictionary
+ if let uid = value?["uid"] as? String {
+ let userPostRef = Database.database().reference()
+ .child("user-posts")
+ .child(uid)
+ .child(postKey)
+ self.incrementStars(forRef: userPostRef)
+ }
+ })
+ }
+ }
+
+ func incrementStars(forRef ref: DatabaseReference) {
+ // [START post_stars_transaction]
+ ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
+ if var post = currentData.value as? [String: AnyObject],
+ let uid = Auth.auth().currentUser?.uid {
+ var stars: [String: Bool]
+ stars = post["stars"] as? [String: Bool] ?? [:]
+ var starCount = post["starCount"] as? Int ?? 0
+ if let _ = stars[uid] {
+ // Unstar the post and remove self from stars
+ starCount -= 1
+ stars.removeValue(forKey: uid)
+ } else {
+ // Star the post and add self to stars
+ starCount += 1
+ stars[uid] = true
+ }
+ post["starCount"] = starCount as AnyObject?
+ post["stars"] = stars as AnyObject?
+
+ // Set value and report transaction success
+ currentData.value = post
+
+ return TransactionResult.success(withValue: currentData)
+ }
+ return TransactionResult.success(withValue: currentData)
+ }) { error, committed, snapshot in
+ if let error = error {
+ print(error.localizedDescription)
+ }
+ }
+ // [END post_stars_transaction]
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/RecentPostsViewController.swift b/qs-snippets/DatabaseExampleSwift/RecentPostsViewController.swift
new file mode 100644
index 00000000..68710f6b
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/RecentPostsViewController.swift
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+
+@objc(RecentPostsViewController)
+class RecentPostsViewController: PostListViewController {
+ override func getQuery() -> DatabaseQuery {
+ // [START recent_posts_query]
+ // Last 100 posts, these are automatically the 100 most recent
+ // due to sorting by push() keys
+ let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
+ // [END recent_posts_query]
+ return recentPostsQuery
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/SignInViewController.swift b/qs-snippets/DatabaseExampleSwift/SignInViewController.swift
new file mode 100644
index 00000000..750b1994
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/SignInViewController.swift
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseAuth
+
+@objc(SignInViewController)
+class SignInViewController: UIViewController, UITextFieldDelegate {
+ @IBOutlet var emailField: UITextField!
+ @IBOutlet var passwordField: UITextField!
+ var ref: DatabaseReference!
+
+ override func touchesBegan(_ touches: Set, with event: UIEvent?) {
+ view.endEditing(true)
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ if Auth.auth().currentUser != nil {
+ performSegue(withIdentifier: "signIn", sender: nil)
+ }
+ ref = Database.database().reference()
+ }
+
+ // Saves user profile information to user database
+ func saveUserInfo(_ user: FirebaseAuth.User, withUsername username: String) {
+ // Create a change request
+ showSpinner {}
+ let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
+ changeRequest?.displayName = username
+
+ // Commit profile changes to server
+ changeRequest?.commitChanges { error in
+
+ self.hideSpinner {}
+
+ if let error = error {
+ self.showMessagePrompt(error.localizedDescription)
+ return
+ }
+
+ // [START basic_write]
+ self.ref.child("users").child(user.uid).setValue(["username": username])
+ // [END basic_write]
+ self.performSegue(withIdentifier: "signIn", sender: nil)
+ }
+ }
+
+ @IBAction func didTapEmailLogin(_ sender: AnyObject) {
+ guard let email = emailField.text, let password = passwordField.text else {
+ showMessagePrompt("email/password can't be empty")
+ return
+ }
+
+ showSpinner {}
+
+ // Sign user in
+ Auth.auth().signIn(withEmail: email, password: password, completion: { authResult, error in
+
+ self.hideSpinner {}
+
+ guard let user = authResult?.user, error == nil else {
+ self.showMessagePrompt(error!.localizedDescription)
+ return
+ }
+
+ self.ref.child("users").child(user.uid).observeSingleEvent(of: .value, with: { snapshot in
+
+ // Check if user already exists
+ guard !snapshot.exists() else {
+ self.performSegue(withIdentifier: "signIn", sender: nil)
+ return
+ }
+
+ // Otherwise, create the new user account
+ self.showTextInputPrompt(withMessage: "Username:") { userPressedOK, username in
+
+ guard let username = username else {
+ self.showMessagePrompt("Username can't be empty")
+ return
+ }
+
+ self.saveUserInfo(user, withUsername: username)
+ }
+ }) // End of observeSingleEvent
+ }) // End of signIn
+ }
+
+ @IBAction func didTapSignUp(_ sender: AnyObject) {
+ func getEmail(completion: @escaping (String) -> Void) {
+ showTextInputPrompt(withMessage: "Email:") { userPressedOK, email in
+ guard let email = email else {
+ self.showMessagePrompt("Email can't be empty.")
+ return
+ }
+ completion(email)
+ }
+ }
+
+ func getUsername(completion: @escaping (String) -> Void) {
+ showTextInputPrompt(withMessage: "Username:") { userPressedOK, username in
+ guard let username = username else {
+ self.showMessagePrompt("Username can't be empty.")
+ return
+ }
+ completion(username)
+ }
+ }
+
+ func getPassword(completion: @escaping (String) -> Void) {
+ showTextInputPrompt(withMessage: "Password:") { userPressedOK, password in
+ guard let password = password else {
+ self.showMessagePrompt("Password can't be empty.")
+ return
+ }
+ completion(password)
+ }
+ }
+
+ // Get the credentials of the user
+ getEmail { email in
+ getUsername { username in
+ getPassword { password in
+
+ // Create the user with the provided credentials
+ Auth.auth()
+ .createUser(withEmail: email, password: password, completion: { authResult, error in
+
+ guard let user = authResult?.user, error == nil else {
+ self.showMessagePrompt(error!.localizedDescription)
+ return
+ }
+
+ // Finally, save their profile
+ self.saveUserInfo(user, withUsername: username)
+
+ })
+ }
+ }
+ }
+ }
+
+ // MARK: - UITextFieldDelegate protocol methods
+
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+ didTapEmailLogin(textField)
+ return true
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/TabBarController.swift b/qs-snippets/DatabaseExampleSwift/TabBarController.swift
new file mode 100644
index 00000000..7bdbd20f
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/TabBarController.swift
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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 FirebaseDatabase
+import FirebaseAuth
+
+@objc(TabBarController)
+class TabBarController: UITabBarController {
+ override func didMove(toParent parent: UIViewController?) {
+ if parent == nil {
+ let firebaseAuth = Auth.auth()
+ do {
+ try firebaseAuth.signOut()
+ } catch let signOutError as NSError {
+ print("Error signing out: %@", signOutError)
+ }
+ }
+ }
+}
diff --git a/qs-snippets/DatabaseExampleSwift/User.swift b/qs-snippets/DatabaseExampleSwift/User.swift
new file mode 100644
index 00000000..e0065b66
--- /dev/null
+++ b/qs-snippets/DatabaseExampleSwift/User.swift
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2015 Google Inc.
+//
+// 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
+
+class User: NSObject {
+ var username: String
+
+ init(username: String) {
+ self.username = username
+ }
+
+ override convenience init() {
+ self.init(username: "")
+ }
+}
diff --git a/qs-snippets/LegacyAuthQuickstart/AuthenticationExample.xcodeproj/project.pbxproj b/qs-snippets/LegacyAuthQuickstart/AuthenticationExample.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..990ddc7a
--- /dev/null
+++ b/qs-snippets/LegacyAuthQuickstart/AuthenticationExample.xcodeproj/project.pbxproj
@@ -0,0 +1,951 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 47;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 107346F52031590C004A66D1 /* AuthenticationExampleSwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 107346F42031590C004A66D1 /* AuthenticationExampleSwiftUITests.swift */; };
+ 1073480D20333B18004A66D1 /* AuthenticationExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1073480C20333B18004A66D1 /* AuthenticationExampleUITests.m */; };
+ 10757BD22059CC9E007623FD /* PasswordlessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10757BD02059CC9E007623FD /* PasswordlessViewController.swift */; };
+ 10757BD52059CFC7007623FD /* PasswordlessViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 10757BD42059CFC7007623FD /* PasswordlessViewController.m */; };
+ 10AF4D111DD3966C0096D192 /* AuthenticationExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 10AF4D101DD3966C0096D192 /* AuthenticationExampleTests.m */; };
+ 10B053F91C6631CD0061077D /* UIViewController+Alerts.m in Sources */ = {isa = PBXBuildFile; fileRef = 10B053F81C6631CD0061077D /* UIViewController+Alerts.m */; };
+ 10B054031C6A3C630061077D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 10B054011C6A3C630061077D /* Main.storyboard */; };
+ 5F5A53521ADE670C00F81DF0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5A53511ADE670C00F81DF0 /* main.m */; };
+ 5F5A53551ADE670C00F81DF0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5A53541ADE670C00F81DF0 /* AppDelegate.m */; };
+ 5F5A537E1ADE67D500F81DF0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F5A537D1ADE67D500F81DF0 /* AppDelegate.swift */; };
+ 5F99610A1AE0CF4F0034F503 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F9961061AE0CF4F0034F503 /* Images.xcassets */; };
+ 5F99610B1AE0CF4F0034F503 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F9961061AE0CF4F0034F503 /* Images.xcassets */; };
+ 5F99610C1AE0CF4F0034F503 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5F9961071AE0CF4F0034F503 /* LaunchScreen.xib */; };
+ 5F99610D1AE0CF4F0034F503 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5F9961071AE0CF4F0034F503 /* LaunchScreen.xib */; };
+ DE31A564244E2B9300A7924A /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE31A55F244DFC9800A7924A /* UIViewController.swift */; };
+ DEC82E4423AAEDF7000EA7B1 /* FIREGSignInHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC82E3F23AAEDEC000EA7B1 /* FIREGSignInHelper.m */; };
+ DEC82E4523AAEDFD000EA7B1 /* FIREGHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC82E4023AAEDEC000EA7B1 /* FIREGHelper.m */; };
+ EF4857041C752B7700649485 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 10B054011C6A3C630061077D /* Main.storyboard */; };
+ EF6DB4CB1CDD60F700319C08 /* CustomTokenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4C81CDD60F700319C08 /* CustomTokenViewController.swift */; };
+ EF6DB4CC1CDD60F700319C08 /* EmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4C91CDD60F700319C08 /* EmailViewController.swift */; };
+ EF6DB4CD1CDD60F700319C08 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4CA1CDD60F700319C08 /* MainViewController.swift */; };
+ EF6DB4D41CDD610200319C08 /* CustomTokenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4CE1CDD610200319C08 /* CustomTokenViewController.m */; };
+ EF6DB4D51CDD610200319C08 /* EmailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4CF1CDD610200319C08 /* EmailViewController.m */; };
+ EF6DB4D61CDD610200319C08 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6DB4D01CDD610200319C08 /* MainViewController.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 107346F72031590C004A66D1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 5F5A53441ADE670C00F81DF0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5F5A53781ADE67D500F81DF0;
+ remoteInfo = AuthenticationExampleSwift;
+ };
+ 1073480F20333B18004A66D1 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 5F5A53441ADE670C00F81DF0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5F5A534B1ADE670C00F81DF0;
+ remoteInfo = AuthenticationExample;
+ };
+ 10AF4D131DD3966C0096D192 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 5F5A53441ADE670C00F81DF0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5F5A534B1ADE670C00F81DF0;
+ remoteInfo = AuthenticationExample;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 107346F22031590C004A66D1 /* AuthenticationExampleSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AuthenticationExampleSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 107346F42031590C004A66D1 /* AuthenticationExampleSwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationExampleSwiftUITests.swift; sourceTree = ""; };
+ 107346F62031590C004A66D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 1073480A20333B18004A66D1 /* AuthenticationExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AuthenticationExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1073480C20333B18004A66D1 /* AuthenticationExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationExampleUITests.m; sourceTree = ""; };
+ 1073480E20333B18004A66D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 10757BD02059CC9E007623FD /* PasswordlessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordlessViewController.swift; sourceTree = ""; };
+ 10757BD32059CFC7007623FD /* PasswordlessViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasswordlessViewController.h; sourceTree = ""; };
+ 10757BD42059CFC7007623FD /* PasswordlessViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PasswordlessViewController.m; sourceTree = ""; };
+ 10757BDD205AD4FC007623FD /* AuthenticationExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AuthenticationExample.entitlements; sourceTree = ""; };
+ 10AF4D0E1DD3966C0096D192 /* AuthenticationExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AuthenticationExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 10AF4D101DD3966C0096D192 /* AuthenticationExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationExampleTests.m; sourceTree = ""; };
+ 10B053F71C6631CD0061077D /* UIViewController+Alerts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Alerts.h"; sourceTree = ""; };
+ 10B053F81C6631CD0061077D /* UIViewController+Alerts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Alerts.m"; sourceTree = ""; };
+ 10B054021C6A3C630061077D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "