Просмотр исходного кода

Add a sample app with SPM and CocoaPods packaging.

Peter Andrews 4 лет назад
Родитель
Сommit
307a42ca3e
68 измененных файлов с 2551 добавлено и 0 удалено
  1. 7 0
      Sample/Podfile
  2. 46 0
      Sample/Resources/DataPickerDictionary.plist
  3. 187 0
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Contents.json
  4. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29.png
  5. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29_2x.png
  6. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29_3x.png
  7. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png
  8. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40_2x.png
  9. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40_3x.png
  10. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-60_2x.png
  11. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-60_3x.png
  12. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png
  13. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-76_2x.png
  14. BIN
      Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-83_2x.png
  15. BIN
      Sample/Resources/PlaceholderAvatar.png
  16. 0 0
      Sample/Resources/ar.lproj/Dummy.strings
  17. 0 0
      Sample/Resources/ca.lproj/Dummy.strings
  18. 0 0
      Sample/Resources/cs.lproj/Dummy.strings
  19. 0 0
      Sample/Resources/da.lproj/Dummy.strings
  20. 0 0
      Sample/Resources/de.lproj/Dummy.strings
  21. 0 0
      Sample/Resources/el.lproj/Dummy.strings
  22. 0 0
      Sample/Resources/en.lproj/Dummy.strings
  23. 0 0
      Sample/Resources/en_GB.lproj/Dummy.strings
  24. 0 0
      Sample/Resources/es.lproj/Dummy.strings
  25. 0 0
      Sample/Resources/es_MX.lproj/Dummy.strings
  26. 0 0
      Sample/Resources/fi.lproj/Dummy.strings
  27. 0 0
      Sample/Resources/fr.lproj/Dummy.strings
  28. 0 0
      Sample/Resources/he.lproj/Dummy.strings
  29. 0 0
      Sample/Resources/hr.lproj/Dummy.strings
  30. 0 0
      Sample/Resources/hu.lproj/Dummy.strings
  31. 0 0
      Sample/Resources/id.lproj/Dummy.strings
  32. 0 0
      Sample/Resources/it.lproj/Dummy.strings
  33. 0 0
      Sample/Resources/ja.lproj/Dummy.strings
  34. 0 0
      Sample/Resources/ko.lproj/Dummy.strings
  35. 0 0
      Sample/Resources/ms.lproj/Dummy.strings
  36. 0 0
      Sample/Resources/nb.lproj/Dummy.strings
  37. 0 0
      Sample/Resources/nl.lproj/Dummy.strings
  38. 0 0
      Sample/Resources/pl.lproj/Dummy.strings
  39. 0 0
      Sample/Resources/pt.lproj/Dummy.strings
  40. 0 0
      Sample/Resources/pt_BR.lproj/Dummy.strings
  41. 0 0
      Sample/Resources/pt_PT.lproj/Dummy.strings
  42. BIN
      Sample/Resources/refresh.png
  43. 0 0
      Sample/Resources/ro.lproj/Dummy.strings
  44. 0 0
      Sample/Resources/ru.lproj/Dummy.strings
  45. 0 0
      Sample/Resources/sk.lproj/Dummy.strings
  46. 0 0
      Sample/Resources/sv.lproj/Dummy.strings
  47. 0 0
      Sample/Resources/th.lproj/Dummy.strings
  48. 0 0
      Sample/Resources/tr.lproj/Dummy.strings
  49. 0 0
      Sample/Resources/uk.lproj/Dummy.strings
  50. 0 0
      Sample/Resources/vi.lproj/Dummy.strings
  51. 0 0
      Sample/Resources/zh_CN.lproj/Dummy.strings
  52. 0 0
      Sample/Resources/zh_TW.lproj/Dummy.strings
  53. 71 0
      Sample/SignInSample-Info.plist
  54. 523 0
      Sample/SignInSample.xcodeproj/project.pbxproj
  55. 542 0
      Sample/SignInSampleForPod.xcodeproj/project.pbxproj
  56. 26 0
      Sample/Source/AppDelegate.h
  57. 57 0
      Sample/Source/AppDelegate.m
  58. 24 0
      Sample/Source/AuthInspectorViewController.h
  59. 143 0
      Sample/Source/AuthInspectorViewController.m
  60. 54 0
      Sample/Source/DataPickerState.h
  61. 59 0
      Sample/Source/DataPickerState.m
  62. 38 0
      Sample/Source/DataPickerViewController.h
  63. 104 0
      Sample/Source/DataPickerViewController.m
  64. 40 0
      Sample/Source/LaunchScreen.xib
  65. 51 0
      Sample/Source/SignInViewController.h
  66. 452 0
      Sample/Source/SignInViewController.m
  67. 101 0
      Sample/Source/SignInViewController.xib
  68. 26 0
      Sample/Source/main.m

+ 7 - 0
Sample/Podfile

@@ -0,0 +1,7 @@
+platform :ios, '9.0'
+use_frameworks!
+
+target 'SampleForPod' do
+  pod 'GoogleSignIn', :path => '../'
+  project 'SignInSampleForPod.xcodeproj'
+end

+ 46 - 0
Sample/Resources/DataPickerDictionary.plist

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Style</key>
+	<dict>
+		<key>multiple-select</key>
+		<false/>
+		<key>elements</key>
+		<array>
+			<dict>
+				<key>label</key>
+				<string>Standard</string>
+				<key>selected</key>
+				<true/>
+			</dict>
+			<dict>
+				<key>label</key>
+				<string>Wide</string>
+			</dict>
+			<dict>
+				<key>label</key>
+				<string>Icon</string>
+			</dict>
+		</array>
+	</dict>
+	<key>Color scheme</key>
+	<dict>
+		<key>multiple-select</key>
+		<false/>
+		<key>elements</key>
+		<array>
+			<dict>
+				<key>label</key>
+				<string>Light</string>
+				<key>selected</key>
+				<true/>
+			</dict>
+			<dict>
+				<key>label</key>
+				<string>Dark</string>
+			</dict>
+		</array>
+	</dict>
+</dict>
+</plist>

+ 187 - 0
Sample/Resources/Images.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,187 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "Icon-29.png",
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "Icon-29_2x.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "Icon-29_3x.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "Icon-40_2x.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "Icon-40_3x.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "40x40"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "57x57"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "57x57"
+    },
+    {
+      "filename" : "Icon-60_2x.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "Icon-60_3x.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "60x60"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "20x20"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "Icon-29.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "Icon-29_2x.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "Icon-40.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "Icon-40_2x.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "50x50"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "50x50"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "72x72"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "72x72"
+    },
+    {
+      "filename" : "Icon-76.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "76x76"
+    },
+    {
+      "filename" : "Icon-76_2x.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "76x76"
+    },
+    {
+      "filename" : "Icon-83_2x.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "83.5x83.5"
+    },
+    {
+      "idiom" : "ios-marketing",
+      "scale" : "1x",
+      "size" : "1024x1024"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "16x16"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "16x16"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "32x32"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "32x32"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "128x128"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "128x128"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "256x256"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "256x256"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29_2x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-29_3x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40_2x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-40_3x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-60_2x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-60_3x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-76_2x.png


BIN
Sample/Resources/Images.xcassets/AppIcon.appiconset/Icon-83_2x.png


BIN
Sample/Resources/PlaceholderAvatar.png


+ 0 - 0
Sample/Resources/ar.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/ca.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/cs.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/da.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/de.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/el.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/en.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/en_GB.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/es.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/es_MX.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/fi.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/fr.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/he.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/hr.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/hu.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/id.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/it.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/ja.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/ko.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/ms.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/nb.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/nl.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/pl.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/pt.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/pt_BR.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/pt_PT.lproj/Dummy.strings


BIN
Sample/Resources/refresh.png


+ 0 - 0
Sample/Resources/ro.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/ru.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/sk.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/sv.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/th.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/tr.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/uk.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/vi.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/zh_CN.lproj/Dummy.strings


+ 0 - 0
Sample/Resources/zh_TW.lproj/Dummy.strings


+ 71 - 0
Sample/SignInSample-Info.plist

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>Sign-In Sample</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIcons</key>
+	<dict>
+		<key>CFBundlePrimaryIcon</key>
+		<dict>
+			<key>CFBundleIconFiles</key>
+			<array>
+				<string>Icon.png</string>
+				<string>Icon-72.png</string>
+				<string>Icon-144.png</string>
+				<string>Icon@2x.png</string>
+			</array>
+		</dict>
+	</dict>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>CFBundleURLName</key>
+			<string>com.googleusercontent.apps.589453917038-qaoga89fitj2ukrsq27ko56fimmojac6</string>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>com.googleusercontent.apps.589453917038-qaoga89fitj2ukrsq27ko56fimmojac6</string>
+			</array>
+		</dict>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

+ 523 - 0
Sample/SignInSample.xcodeproj/project.pbxproj

@@ -0,0 +1,523 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 52;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		C1E69232264315E7004CE2BC /* SignInViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E69226264315E7004CE2BC /* SignInViewController.m */; };
+		C1E69233264315E7004CE2BC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = C1E69228264315E7004CE2BC /* LaunchScreen.xib */; };
+		C1E69234264315E7004CE2BC /* DataPickerState.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E6922A264315E7004CE2BC /* DataPickerState.m */; };
+		C1E69235264315E7004CE2BC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E6922B264315E7004CE2BC /* main.m */; };
+		C1E69236264315E7004CE2BC /* DataPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E6922C264315E7004CE2BC /* DataPickerViewController.m */; };
+		C1E69237264315E7004CE2BC /* SignInViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C1E6922D264315E7004CE2BC /* SignInViewController.xib */; };
+		C1E69238264315E7004CE2BC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E6922F264315E7004CE2BC /* AppDelegate.m */; };
+		C1E69239264315E7004CE2BC /* AuthInspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C1E69231264315E7004CE2BC /* AuthInspectorViewController.m */; };
+		C1E6924426431A6D004CE2BC /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = C1E6924326431A6D004CE2BC /* GoogleSignIn */; };
+		C1E6927C26431E13004CE2BC /* Dummy.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1E6925326431E12004CE2BC /* Dummy.strings */; };
+		C1E6927D26431E13004CE2BC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C1E6926E26431E13004CE2BC /* Images.xcassets */; };
+		C1E6927E26431E13004CE2BC /* DataPickerDictionary.plist in Resources */ = {isa = PBXBuildFile; fileRef = C1E6927026431E13004CE2BC /* DataPickerDictionary.plist */; };
+		C1E6927F26431E13004CE2BC /* PlaceholderAvatar.png in Resources */ = {isa = PBXBuildFile; fileRef = C1E6927426431E13004CE2BC /* PlaceholderAvatar.png */; };
+		C1E6928026431E13004CE2BC /* refresh.png in Resources */ = {isa = PBXBuildFile; fileRef = C1E6927926431E13004CE2BC /* refresh.png */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		C15484C022FCB34100C76691 /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = System/Library/Frameworks/AuthenticationServices.framework; sourceTree = SDKROOT; };
+		C1E69225264315E7004CE2BC /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		C1E69226264315E7004CE2BC /* SignInViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignInViewController.m; sourceTree = "<group>"; };
+		C1E69227264315E7004CE2BC /* DataPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataPickerViewController.h; sourceTree = "<group>"; };
+		C1E69228264315E7004CE2BC /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
+		C1E69229264315E7004CE2BC /* AuthInspectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthInspectorViewController.h; sourceTree = "<group>"; };
+		C1E6922A264315E7004CE2BC /* DataPickerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataPickerState.m; sourceTree = "<group>"; };
+		C1E6922B264315E7004CE2BC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		C1E6922C264315E7004CE2BC /* DataPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataPickerViewController.m; sourceTree = "<group>"; };
+		C1E6922D264315E7004CE2BC /* SignInViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SignInViewController.xib; sourceTree = "<group>"; };
+		C1E6922E264315E7004CE2BC /* SignInViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignInViewController.h; sourceTree = "<group>"; };
+		C1E6922F264315E7004CE2BC /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		C1E69230264315E7004CE2BC /* DataPickerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataPickerState.h; sourceTree = "<group>"; };
+		C1E69231264315E7004CE2BC /* AuthInspectorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthInspectorViewController.m; sourceTree = "<group>"; };
+		C1E6923C2643162E004CE2BC /* SignInSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SignInSample-Info.plist"; sourceTree = "<group>"; };
+		C1E6925426431E13004CE2BC /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925526431E13004CE2BC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925626431E13004CE2BC /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925726431E13004CE2BC /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925826431E13004CE2BC /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925926431E13004CE2BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925A26431E13004CE2BC /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925B26431E13004CE2BC /* es_MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es_MX; path = es_MX.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925C26431E13004CE2BC /* zh_CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_CN; path = zh_CN.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925D26431E13004CE2BC /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925E26431E13004CE2BC /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6925F26431E13004CE2BC /* pt_BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt_BR; path = pt_BR.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926026431E13004CE2BC /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926126431E13004CE2BC /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926226431E13004CE2BC /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926326431E13004CE2BC /* pt_PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt_PT; path = pt_PT.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926426431E13004CE2BC /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926526431E13004CE2BC /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926626431E13004CE2BC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926726431E13004CE2BC /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926826431E13004CE2BC /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926926431E13004CE2BC /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926A26431E13004CE2BC /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926B26431E13004CE2BC /* zh_TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_TW; path = zh_TW.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926C26431E13004CE2BC /* en_GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en_GB; path = en_GB.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926D26431E13004CE2BC /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6926E26431E13004CE2BC /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+		C1E6926F26431E13004CE2BC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927026431E13004CE2BC /* DataPickerDictionary.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DataPickerDictionary.plist; sourceTree = "<group>"; };
+		C1E6927126431E13004CE2BC /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927226431E13004CE2BC /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927326431E13004CE2BC /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927426431E13004CE2BC /* PlaceholderAvatar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PlaceholderAvatar.png; sourceTree = "<group>"; };
+		C1E6927526431E13004CE2BC /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927626431E13004CE2BC /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927726431E13004CE2BC /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927826431E13004CE2BC /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927926431E13004CE2BC /* refresh.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = refresh.png; sourceTree = "<group>"; };
+		C1E6927A26431E13004CE2BC /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6927B26431E13004CE2BC /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Dummy.strings; sourceTree = "<group>"; };
+		C1E6928826436CFB004CE2BC /* GoogleSignIn-iOS */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "GoogleSignIn-iOS"; path = ..; sourceTree = "<group>"; };
+		D936C1C821225D1000E8DAC9 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
+		D99924CA1A92B3C7008CC226 /* SignInSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SignInSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		D99925141A92B5A8008CC226 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		D9D3B1D91B72A28500D2EAA2 /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = System/Library/Frameworks/SafariServices.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D99924C71A92B3C7008CC226 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				C1E6924426431A6D004CE2BC /* GoogleSignIn in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		C1E69224264315E7004CE2BC /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				C1E69225264315E7004CE2BC /* AppDelegate.h */,
+				C1E6922F264315E7004CE2BC /* AppDelegate.m */,
+				C1E69229264315E7004CE2BC /* AuthInspectorViewController.h */,
+				C1E69231264315E7004CE2BC /* AuthInspectorViewController.m */,
+				C1E69230264315E7004CE2BC /* DataPickerState.h */,
+				C1E6922A264315E7004CE2BC /* DataPickerState.m */,
+				C1E69227264315E7004CE2BC /* DataPickerViewController.h */,
+				C1E6922C264315E7004CE2BC /* DataPickerViewController.m */,
+				C1E69228264315E7004CE2BC /* LaunchScreen.xib */,
+				C1E6922B264315E7004CE2BC /* main.m */,
+				C1E6922E264315E7004CE2BC /* SignInViewController.h */,
+				C1E69226264315E7004CE2BC /* SignInViewController.m */,
+				C1E6922D264315E7004CE2BC /* SignInViewController.xib */,
+			);
+			path = Source;
+			sourceTree = "<group>";
+		};
+		C1E6925226431E12004CE2BC /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				C1E6925326431E12004CE2BC /* Dummy.strings */,
+				C1E6926E26431E13004CE2BC /* Images.xcassets */,
+				C1E6927026431E13004CE2BC /* DataPickerDictionary.plist */,
+				C1E6927426431E13004CE2BC /* PlaceholderAvatar.png */,
+				C1E6927926431E13004CE2BC /* refresh.png */,
+			);
+			path = Resources;
+			sourceTree = "<group>";
+		};
+		D99924C11A92B3C7008CC226 = {
+			isa = PBXGroup;
+			children = (
+				C1E6928826436CFB004CE2BC /* GoogleSignIn-iOS */,
+				C1E6923C2643162E004CE2BC /* SignInSample-Info.plist */,
+				C1E69224264315E7004CE2BC /* Source */,
+				C1E6925226431E12004CE2BC /* Resources */,
+				D999250F1A92B555008CC226 /* Frameworks */,
+				D99924CB1A92B3C7008CC226 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		D99924CB1A92B3C7008CC226 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D99924CA1A92B3C7008CC226 /* SignInSample.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		D999250F1A92B555008CC226 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				C15484C022FCB34100C76691 /* AuthenticationServices.framework */,
+				D936C1C821225D1000E8DAC9 /* LocalAuthentication.framework */,
+				D9D3B1D91B72A28500D2EAA2 /* SafariServices.framework */,
+				D99925141A92B5A8008CC226 /* SystemConfiguration.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		D99924C91A92B3C7008CC226 /* SignInSample */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D99924ED1A92B3C7008CC226 /* Build configuration list for PBXNativeTarget "SignInSample" */;
+			buildPhases = (
+				D99924C61A92B3C7008CC226 /* Sources */,
+				D99924C71A92B3C7008CC226 /* Frameworks */,
+				D99924C81A92B3C7008CC226 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = SignInSample;
+			packageProductDependencies = (
+				C1E6924326431A6D004CE2BC /* GoogleSignIn */,
+			);
+			productName = SignInSample;
+			productReference = D99924CA1A92B3C7008CC226 /* SignInSample.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		D99924C21A92B3C7008CC226 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1240;
+				ORGANIZATIONNAME = "Google Inc";
+				TargetAttributes = {
+					D99924C91A92B3C7008CC226 = {
+						CreatedOnToolsVersion = 6.1.1;
+					};
+				};
+			};
+			buildConfigurationList = D99924C51A92B3C7008CC226 /* Build configuration list for PBXProject "SignInSample" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+				de,
+				he,
+				ar,
+				el,
+				ja,
+				uk,
+				es_MX,
+				zh_CN,
+				nb,
+				es,
+				pt_BR,
+				da,
+				it,
+				sk,
+				pt_PT,
+				ms,
+				sv,
+				cs,
+				ko,
+				hu,
+				tr,
+				pl,
+				zh_TW,
+				en_GB,
+				vi,
+				ru,
+				fr,
+				fi,
+				id,
+				nl,
+				th,
+				pt,
+				ro,
+				hr,
+				ca,
+			);
+			mainGroup = D99924C11A92B3C7008CC226;
+			packageReferences = (
+				C1E6924226431A6D004CE2BC /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */,
+			);
+			productRefGroup = D99924CB1A92B3C7008CC226 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D99924C91A92B3C7008CC226 /* SignInSample */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		D99924C81A92B3C7008CC226 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				C1E6927F26431E13004CE2BC /* PlaceholderAvatar.png in Resources */,
+				C1E6927D26431E13004CE2BC /* Images.xcassets in Resources */,
+				C1E6927E26431E13004CE2BC /* DataPickerDictionary.plist in Resources */,
+				C1E6927C26431E13004CE2BC /* Dummy.strings in Resources */,
+				C1E6928026431E13004CE2BC /* refresh.png in Resources */,
+				C1E69233264315E7004CE2BC /* LaunchScreen.xib in Resources */,
+				C1E69237264315E7004CE2BC /* SignInViewController.xib in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D99924C61A92B3C7008CC226 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				C1E69239264315E7004CE2BC /* AuthInspectorViewController.m in Sources */,
+				C1E69238264315E7004CE2BC /* AppDelegate.m in Sources */,
+				C1E69232264315E7004CE2BC /* SignInViewController.m in Sources */,
+				C1E69236264315E7004CE2BC /* DataPickerViewController.m in Sources */,
+				C1E69234264315E7004CE2BC /* DataPickerState.m in Sources */,
+				C1E69235264315E7004CE2BC /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		C1E6925326431E12004CE2BC /* Dummy.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				C1E6925426431E13004CE2BC /* de */,
+				C1E6925526431E13004CE2BC /* he */,
+				C1E6925626431E13004CE2BC /* ar */,
+				C1E6925726431E13004CE2BC /* el */,
+				C1E6925826431E13004CE2BC /* ja */,
+				C1E6925926431E13004CE2BC /* en */,
+				C1E6925A26431E13004CE2BC /* uk */,
+				C1E6925B26431E13004CE2BC /* es_MX */,
+				C1E6925C26431E13004CE2BC /* zh_CN */,
+				C1E6925D26431E13004CE2BC /* nb */,
+				C1E6925E26431E13004CE2BC /* es */,
+				C1E6925F26431E13004CE2BC /* pt_BR */,
+				C1E6926026431E13004CE2BC /* da */,
+				C1E6926126431E13004CE2BC /* it */,
+				C1E6926226431E13004CE2BC /* sk */,
+				C1E6926326431E13004CE2BC /* pt_PT */,
+				C1E6926426431E13004CE2BC /* ms */,
+				C1E6926526431E13004CE2BC /* sv */,
+				C1E6926626431E13004CE2BC /* cs */,
+				C1E6926726431E13004CE2BC /* ko */,
+				C1E6926826431E13004CE2BC /* hu */,
+				C1E6926926431E13004CE2BC /* tr */,
+				C1E6926A26431E13004CE2BC /* pl */,
+				C1E6926B26431E13004CE2BC /* zh_TW */,
+				C1E6926C26431E13004CE2BC /* en_GB */,
+				C1E6926D26431E13004CE2BC /* vi */,
+				C1E6926F26431E13004CE2BC /* ru */,
+				C1E6927126431E13004CE2BC /* fr */,
+				C1E6927226431E13004CE2BC /* fi */,
+				C1E6927326431E13004CE2BC /* id */,
+				C1E6927526431E13004CE2BC /* nl */,
+				C1E6927626431E13004CE2BC /* th */,
+				C1E6927726431E13004CE2BC /* pt */,
+				C1E6927826431E13004CE2BC /* ro */,
+				C1E6927A26431E13004CE2BC /* hr */,
+				C1E6927B26431E13004CE2BC /* ca */,
+			);
+			name = Dummy.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		D99924EB1A92B3C7008CC226 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				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_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;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = 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 = 9.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		D99924EC1A92B3C7008CC226 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				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_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;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				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 = 9.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "-ObjC";
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		D99924EE1A92B3C7008CC226 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					..,
+				);
+				INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		D99924EF1A92B3C7008CC226 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					..,
+				);
+				INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		D99924C51A92B3C7008CC226 /* Build configuration list for PBXProject "SignInSample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D99924EB1A92B3C7008CC226 /* Debug */,
+				D99924EC1A92B3C7008CC226 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		D99924ED1A92B3C7008CC226 /* Build configuration list for PBXNativeTarget "SignInSample" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D99924EE1A92B3C7008CC226 /* Debug */,
+				D99924EF1A92B3C7008CC226 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+		C1E6924226431A6D004CE2BC /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/google/GoogleSignIn-iOS.git";
+			requirement = {
+				branch = main;
+				kind = branch;
+			};
+		};
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+		C1E6924326431A6D004CE2BC /* GoogleSignIn */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = C1E6924226431A6D004CE2BC /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */;
+			productName = GoogleSignIn;
+		};
+/* End XCSwiftPackageProductDependency section */
+	};
+	rootObject = D99924C21A92B3C7008CC226 /* Project object */;
+}

+ 542 - 0
Sample/SignInSampleForPod.xcodeproj/project.pbxproj

@@ -0,0 +1,542 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CC887BA946C6A9FDA3DE81B5 /* Pods_SampleForPod.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */; };
+		D926A5701BC3236100ADECE6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A5381BC3236100ADECE6 /* AppDelegate.m */; };
+		D926A5711BC3236100ADECE6 /* AuthInspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53A1BC3236100ADECE6 /* AuthInspectorViewController.m */; };
+		D926A5721BC3236100ADECE6 /* DataPickerState.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53C1BC3236100ADECE6 /* DataPickerState.m */; };
+		D926A5731BC3236100ADECE6 /* DataPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A53E1BC3236100ADECE6 /* DataPickerViewController.m */; };
+		D926A5741BC3236100ADECE6 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D926A53F1BC3236100ADECE6 /* LaunchScreen.xib */; };
+		D926A5751BC3236100ADECE6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A5401BC3236100ADECE6 /* main.m */; };
+		D926A5761BC3236100ADECE6 /* Dummy.strings in Resources */ = {isa = PBXBuildFile; fileRef = D926A5421BC3236100ADECE6 /* Dummy.strings */; };
+		D926A5771BC3236100ADECE6 /* DataPickerDictionary.plist in Resources */ = {isa = PBXBuildFile; fileRef = D926A5471BC3236100ADECE6 /* DataPickerDictionary.plist */; };
+		D926A5781BC3236100ADECE6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D926A5541BC3236100ADECE6 /* Images.xcassets */; };
+		D926A5791BC3236100ADECE6 /* PlaceholderAvatar.png in Resources */ = {isa = PBXBuildFile; fileRef = D926A55C1BC3236100ADECE6 /* PlaceholderAvatar.png */; };
+		D926A57A1BC3236100ADECE6 /* refresh.png in Resources */ = {isa = PBXBuildFile; fileRef = D926A5601BC3236100ADECE6 /* refresh.png */; };
+		D926A57D1BC3236100ADECE6 /* SignInViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D926A56E1BC3236100ADECE6 /* SignInViewController.m */; };
+		D926A57E1BC3236100ADECE6 /* SignInViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D926A56F1BC3236100ADECE6 /* SignInViewController.xib */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleForPod.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		D926A51D1BC31FE000ADECE6 /* SignInSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SignInSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		D926A5371BC3236100ADECE6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Source/AppDelegate.h; sourceTree = SOURCE_ROOT; };
+		D926A5381BC3236100ADECE6 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Source/AppDelegate.m; sourceTree = SOURCE_ROOT; };
+		D926A5391BC3236100ADECE6 /* AuthInspectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthInspectorViewController.h; path = Source/AuthInspectorViewController.h; sourceTree = SOURCE_ROOT; };
+		D926A53A1BC3236100ADECE6 /* AuthInspectorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AuthInspectorViewController.m; path = Source/AuthInspectorViewController.m; sourceTree = SOURCE_ROOT; };
+		D926A53B1BC3236100ADECE6 /* DataPickerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataPickerState.h; path = Source/DataPickerState.h; sourceTree = SOURCE_ROOT; };
+		D926A53C1BC3236100ADECE6 /* DataPickerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DataPickerState.m; path = Source/DataPickerState.m; sourceTree = SOURCE_ROOT; };
+		D926A53D1BC3236100ADECE6 /* DataPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataPickerViewController.h; path = Source/DataPickerViewController.h; sourceTree = SOURCE_ROOT; };
+		D926A53E1BC3236100ADECE6 /* DataPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DataPickerViewController.m; path = Source/DataPickerViewController.m; sourceTree = SOURCE_ROOT; };
+		D926A53F1BC3236100ADECE6 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = LaunchScreen.xib; path = Source/LaunchScreen.xib; sourceTree = SOURCE_ROOT; };
+		D926A5401BC3236100ADECE6 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Source/main.m; sourceTree = SOURCE_ROOT; };
+		D926A5431BC3236100ADECE6 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5441BC3236100ADECE6 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5451BC3236100ADECE6 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5461BC3236100ADECE6 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5471BC3236100ADECE6 /* DataPickerDictionary.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DataPickerDictionary.plist; sourceTree = "<group>"; };
+		D926A5481BC3236100ADECE6 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5491BC3236100ADECE6 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54A1BC3236100ADECE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54B1BC3236100ADECE6 /* en_GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en_GB; path = en_GB.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54C1BC3236100ADECE6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54D1BC3236100ADECE6 /* es_MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es_MX; path = es_MX.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54E1BC3236100ADECE6 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A54F1BC3236100ADECE6 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5501BC3236100ADECE6 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5511BC3236100ADECE6 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5521BC3236100ADECE6 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5531BC3236100ADECE6 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5541BC3236100ADECE6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+		D926A5551BC3236100ADECE6 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5561BC3236100ADECE6 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5571BC3236100ADECE6 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5581BC3236100ADECE6 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5591BC3236100ADECE6 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A55A1BC3236100ADECE6 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A55B1BC3236100ADECE6 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A55C1BC3236100ADECE6 /* PlaceholderAvatar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PlaceholderAvatar.png; sourceTree = "<group>"; };
+		D926A55D1BC3236100ADECE6 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A55E1BC3236100ADECE6 /* pt_BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt_BR; path = pt_BR.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A55F1BC3236100ADECE6 /* pt_PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt_PT; path = pt_PT.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5601BC3236100ADECE6 /* refresh.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = refresh.png; sourceTree = "<group>"; };
+		D926A5611BC3236100ADECE6 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5621BC3236100ADECE6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5631BC3236100ADECE6 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5641BC3236100ADECE6 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5651BC3236100ADECE6 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5661BC3236100ADECE6 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5671BC3236100ADECE6 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5681BC3236100ADECE6 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A5691BC3236100ADECE6 /* zh_CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_CN; path = zh_CN.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A56A1BC3236100ADECE6 /* zh_TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_TW; path = zh_TW.lproj/Dummy.strings; sourceTree = "<group>"; };
+		D926A56B1BC3236100ADECE6 /* SignInSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SignInSample-Info.plist"; sourceTree = SOURCE_ROOT; };
+		D926A56D1BC3236100ADECE6 /* SignInViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SignInViewController.h; path = Source/SignInViewController.h; sourceTree = SOURCE_ROOT; };
+		D926A56E1BC3236100ADECE6 /* SignInViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SignInViewController.m; path = Source/SignInViewController.m; sourceTree = SOURCE_ROOT; };
+		D926A56F1BC3236100ADECE6 /* SignInViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SignInViewController.xib; path = Source/SignInViewController.xib; sourceTree = SOURCE_ROOT; };
+		DAD21F7A41C90200270A7376 /* Pods-SampleForPod.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleForPod.release.xcconfig"; path = "Target Support Files/Pods-SampleForPod/Pods-SampleForPod.release.xcconfig"; sourceTree = "<group>"; };
+		FE1798D23522F57E24875676 /* Pods-SampleForPod.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleForPod.debug.xcconfig"; path = "Target Support Files/Pods-SampleForPod/Pods-SampleForPod.debug.xcconfig"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D926A51A1BC31FE000ADECE6 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CC887BA946C6A9FDA3DE81B5 /* Pods_SampleForPod.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		19474CEE103056649A5A84AC /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				FE1798D23522F57E24875676 /* Pods-SampleForPod.debug.xcconfig */,
+				DAD21F7A41C90200270A7376 /* Pods-SampleForPod.release.xcconfig */,
+			);
+			path = Pods;
+			sourceTree = "<group>";
+		};
+		BB0E907DD016FB9CB6DC01B5 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				550F5407FA6F32CFDE2C3C75 /* Pods_SampleForPod.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		C1E6921F26431165004CE2BC /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				D926A5371BC3236100ADECE6 /* AppDelegate.h */,
+				D926A5381BC3236100ADECE6 /* AppDelegate.m */,
+				D926A5391BC3236100ADECE6 /* AuthInspectorViewController.h */,
+				D926A53A1BC3236100ADECE6 /* AuthInspectorViewController.m */,
+				D926A53B1BC3236100ADECE6 /* DataPickerState.h */,
+				D926A53C1BC3236100ADECE6 /* DataPickerState.m */,
+				D926A53D1BC3236100ADECE6 /* DataPickerViewController.h */,
+				D926A53E1BC3236100ADECE6 /* DataPickerViewController.m */,
+				D926A53F1BC3236100ADECE6 /* LaunchScreen.xib */,
+				D926A5401BC3236100ADECE6 /* main.m */,
+				D926A56D1BC3236100ADECE6 /* SignInViewController.h */,
+				D926A56E1BC3236100ADECE6 /* SignInViewController.m */,
+				D926A56F1BC3236100ADECE6 /* SignInViewController.xib */,
+			);
+			path = Source;
+			sourceTree = "<group>";
+		};
+		D926A5141BC31FE000ADECE6 = {
+			isa = PBXGroup;
+			children = (
+				D926A56B1BC3236100ADECE6 /* SignInSample-Info.plist */,
+				C1E6921F26431165004CE2BC /* Source */,
+				D926A5411BC3236100ADECE6 /* Resources */,
+				D926A51E1BC31FE000ADECE6 /* Products */,
+				19474CEE103056649A5A84AC /* Pods */,
+				BB0E907DD016FB9CB6DC01B5 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		D926A51E1BC31FE000ADECE6 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D926A51D1BC31FE000ADECE6 /* SignInSample.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		D926A5411BC3236100ADECE6 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				D926A5421BC3236100ADECE6 /* Dummy.strings */,
+				D926A5471BC3236100ADECE6 /* DataPickerDictionary.plist */,
+				D926A5541BC3236100ADECE6 /* Images.xcassets */,
+				D926A55C1BC3236100ADECE6 /* PlaceholderAvatar.png */,
+				D926A5601BC3236100ADECE6 /* refresh.png */,
+			);
+			path = Resources;
+			sourceTree = SOURCE_ROOT;
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		D926A51C1BC31FE000ADECE6 /* SampleForPod */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D926A5341BC31FE000ADECE6 /* Build configuration list for PBXNativeTarget "SampleForPod" */;
+			buildPhases = (
+				4E03DCAF883884540B8AF6E6 /* [CP] Check Pods Manifest.lock */,
+				D926A5191BC31FE000ADECE6 /* Sources */,
+				D926A51A1BC31FE000ADECE6 /* Frameworks */,
+				D926A51B1BC31FE000ADECE6 /* Resources */,
+				819CCDEFD018D376E185A11E /* [CP] Embed Pods Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = SampleForPod;
+			productName = SampleForPod;
+			productReference = D926A51D1BC31FE000ADECE6 /* SignInSample.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		D926A5151BC31FE000ADECE6 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1240;
+				ORGANIZATIONNAME = "Google Inc";
+				TargetAttributes = {
+					D926A51C1BC31FE000ADECE6 = {
+						CreatedOnToolsVersion = 7.0;
+					};
+				};
+			};
+			buildConfigurationList = D926A5181BC31FE000ADECE6 /* Build configuration list for PBXProject "SignInSampleForPod" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+				ar,
+				ca,
+				cs,
+				da,
+				de,
+				el,
+				en_GB,
+				es,
+				es_MX,
+				fi,
+				fr,
+				he,
+				hr,
+				hu,
+				id,
+				it,
+				ja,
+				ko,
+				ms,
+				nb,
+				nl,
+				pl,
+				pt,
+				pt_BR,
+				pt_PT,
+				ro,
+				ru,
+				sk,
+				sv,
+				th,
+				tr,
+				uk,
+				vi,
+				zh_CN,
+				zh_TW,
+			);
+			mainGroup = D926A5141BC31FE000ADECE6;
+			productRefGroup = D926A51E1BC31FE000ADECE6 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D926A51C1BC31FE000ADECE6 /* SampleForPod */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		D926A51B1BC31FE000ADECE6 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D926A5791BC3236100ADECE6 /* PlaceholderAvatar.png in Resources */,
+				D926A57A1BC3236100ADECE6 /* refresh.png in Resources */,
+				D926A5741BC3236100ADECE6 /* LaunchScreen.xib in Resources */,
+				D926A5781BC3236100ADECE6 /* Images.xcassets in Resources */,
+				D926A5761BC3236100ADECE6 /* Dummy.strings in Resources */,
+				D926A57E1BC3236100ADECE6 /* SignInViewController.xib in Resources */,
+				D926A5771BC3236100ADECE6 /* DataPickerDictionary.plist in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		4E03DCAF883884540B8AF6E6 /* [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-SampleForPod-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;
+		};
+		819CCDEFD018D376E185A11E /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-SampleForPod/Pods-SampleForPod-frameworks.sh",
+				"${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework",
+				"${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework",
+				"${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework",
+				"${BUILT_PRODUCTS_DIR}/GoogleSignIn/GoogleSignIn.framework",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleSignIn.framework",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleForPod/Pods-SampleForPod-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D926A5191BC31FE000ADECE6 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D926A5751BC3236100ADECE6 /* main.m in Sources */,
+				D926A5731BC3236100ADECE6 /* DataPickerViewController.m in Sources */,
+				D926A5721BC3236100ADECE6 /* DataPickerState.m in Sources */,
+				D926A5711BC3236100ADECE6 /* AuthInspectorViewController.m in Sources */,
+				D926A57D1BC3236100ADECE6 /* SignInViewController.m in Sources */,
+				D926A5701BC3236100ADECE6 /* AppDelegate.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		D926A5421BC3236100ADECE6 /* Dummy.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				D926A5431BC3236100ADECE6 /* ar */,
+				D926A5441BC3236100ADECE6 /* ca */,
+				D926A5451BC3236100ADECE6 /* cs */,
+				D926A5461BC3236100ADECE6 /* da */,
+				D926A5481BC3236100ADECE6 /* de */,
+				D926A5491BC3236100ADECE6 /* el */,
+				D926A54A1BC3236100ADECE6 /* en */,
+				D926A54B1BC3236100ADECE6 /* en_GB */,
+				D926A54C1BC3236100ADECE6 /* es */,
+				D926A54D1BC3236100ADECE6 /* es_MX */,
+				D926A54E1BC3236100ADECE6 /* fi */,
+				D926A54F1BC3236100ADECE6 /* fr */,
+				D926A5501BC3236100ADECE6 /* he */,
+				D926A5511BC3236100ADECE6 /* hr */,
+				D926A5521BC3236100ADECE6 /* hu */,
+				D926A5531BC3236100ADECE6 /* id */,
+				D926A5551BC3236100ADECE6 /* it */,
+				D926A5561BC3236100ADECE6 /* ja */,
+				D926A5571BC3236100ADECE6 /* ko */,
+				D926A5581BC3236100ADECE6 /* ms */,
+				D926A5591BC3236100ADECE6 /* nb */,
+				D926A55A1BC3236100ADECE6 /* nl */,
+				D926A55B1BC3236100ADECE6 /* pl */,
+				D926A55D1BC3236100ADECE6 /* pt */,
+				D926A55E1BC3236100ADECE6 /* pt_BR */,
+				D926A55F1BC3236100ADECE6 /* pt_PT */,
+				D926A5611BC3236100ADECE6 /* ro */,
+				D926A5621BC3236100ADECE6 /* ru */,
+				D926A5631BC3236100ADECE6 /* sk */,
+				D926A5641BC3236100ADECE6 /* sv */,
+				D926A5651BC3236100ADECE6 /* th */,
+				D926A5661BC3236100ADECE6 /* tr */,
+				D926A5671BC3236100ADECE6 /* uk */,
+				D926A5681BC3236100ADECE6 /* vi */,
+				D926A5691BC3236100ADECE6 /* zh_CN */,
+				D926A56A1BC3236100ADECE6 /* zh_TW */,
+			);
+			name = Dummy.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		D926A5321BC31FE000ADECE6 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				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_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;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				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_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 = 9.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		D926A5331BC31FE000ADECE6 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				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_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;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "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 = 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 = 9.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		D926A5351BC31FE000ADECE6 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = FE1798D23522F57E24875676 /* Pods-SampleForPod.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.SignInSample;
+				PRODUCT_NAME = SignInSample;
+			};
+			name = Debug;
+		};
+		D926A5361BC31FE000ADECE6 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = DAD21F7A41C90200270A7376 /* Pods-SampleForPod.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = "$(SRCROOT)/SignInSample-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.SignInSample;
+				PRODUCT_NAME = SignInSample;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		D926A5181BC31FE000ADECE6 /* Build configuration list for PBXProject "SignInSampleForPod" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D926A5321BC31FE000ADECE6 /* Debug */,
+				D926A5331BC31FE000ADECE6 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		D926A5341BC31FE000ADECE6 /* Build configuration list for PBXNativeTarget "SampleForPod" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D926A5351BC31FE000ADECE6 /* Debug */,
+				D926A5361BC31FE000ADECE6 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = D926A5151BC31FE000ADECE6 /* Project object */;
+}

+ 26 - 0
Sample/Source/AppDelegate.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright 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 <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder<UIApplicationDelegate>
+
+// The sample app's |UIWindow|.
+@property(strong, nonatomic) UIWindow *window;
+// The navigation controller.
+@property(strong, nonatomic) UINavigationController *navigationController;
+
+@end

+ 57 - 0
Sample/Source/AppDelegate.m

@@ -0,0 +1,57 @@
+/*
+ * Copyright 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 "AppDelegate.h"
+
+#import "SignInViewController.h"
+
+@import GoogleSignIn;
+
+@implementation AppDelegate
+
+// DO NOT USE THIS CLIENT ID. IT WILL NOT WORK FOR YOUR APP.
+// Please use the client ID created for you by Google.
+static NSString * const kClientID =
+    @"589453917038-qaoga89fitj2ukrsq27ko56fimmojac6.apps.googleusercontent.com";
+
+#pragma mark Object life-cycle.
+
+- (BOOL)application:(UIApplication *)application
+    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+  // Set app's client ID for |GIDSignIn|.
+  [GIDSignIn sharedInstance].clientID = kClientID;
+
+  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+  SignInViewController *masterViewController =
+      [[SignInViewController alloc] initWithNibName:@"SignInViewController"
+                                             bundle:nil];
+  self.navigationController =
+      [[UINavigationController alloc]
+          initWithRootViewController:masterViewController];
+  self.window.rootViewController = self.navigationController;
+  [self.window makeKeyAndVisible];
+
+  return YES;
+}
+
+- (BOOL)application:(UIApplication *)app
+            openURL:(NSURL *)url
+            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
+  return [[GIDSignIn sharedInstance] handleURL:url];
+}
+
+
+@end

+ 24 - 0
Sample/Source/AuthInspectorViewController.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright 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 <UIKit/UIKit.h>
+
+// A view controller for inspecting the various properties stored in the
+// |GIDSignIn| object.
+@interface AuthInspectorViewController : UIViewController
+
+@end
+

+ 143 - 0
Sample/Source/AuthInspectorViewController.m

@@ -0,0 +1,143 @@
+/*
+ * Copyright 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 "AuthInspectorViewController.h"
+
+@import GoogleSignIn;
+
+static NSString * const kReusableCellIdentifier = @"AuthInspectorCell";
+static CGFloat const kVeryTallConstraint = 10000.f;
+static CGFloat const kTableViewCellFontSize = 16.f;
+static CGFloat const kTableViewCellPadding = 22.f;
+
+@interface AuthInspectorViewController () <UITableViewDataSource, UITableViewDelegate>
+
+@end
+
+@implementation AuthInspectorViewController {
+  // Key-paths for the GIDSignIn instance to inspect.
+  NSArray *_keyPaths;
+}
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+  if (self) {
+    _keyPaths = @[
+      @"authentication.accessToken",
+      @"authentication.accessTokenExpirationDate",
+      @"authentication.refreshToken",
+      @"authentication.idToken",
+      @"grantedScopes",
+      @"userID",
+      @"serverAuthCode",
+      @"profile.email",
+      @"profile.name",
+    ];
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero
+                                                        style:UITableViewStyleGrouped];
+  tableView.delegate = self;
+  tableView.dataSource = self;
+  tableView.frame = self.view.bounds;
+  [self.view addSubview:tableView];
+}
+
+- (void)viewDidLayoutSubviews {
+  if (self.view.subviews.count) {
+    ((UIView *)self.view.subviews[0]).frame = self.view.bounds;
+  }
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+  return (NSInteger)[_keyPaths count];
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
+  return [self contentForSectionHeader:section];
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+  return 1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kReusableCellIdentifier];
+  if (!cell) {
+    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
+                                   reuseIdentifier:kReusableCellIdentifier];
+  }
+  cell.textLabel.font = [UIFont systemFontOfSize:kTableViewCellFontSize];
+  cell.textLabel.numberOfLines = 0;
+  cell.textLabel.text = [self contentForRowAtIndexPath:indexPath];
+  cell.selectionStyle = UITableViewCellSelectionStyleNone;
+
+  return cell;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView *)tableView
+    willDisplayHeaderView:(UIView *)view
+               forSection:(NSInteger)section {
+  // The default header view capitalizes the title, which we don't want (because it's the key path).
+  if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) {
+    ((UITableViewHeaderFooterView *)view).textLabel.text = [self contentForSectionHeader:section];
+  }
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
+  return [self heightForTableView:tableView content:[self contentForSectionHeader:section]]
+      - (section ? kTableViewCellPadding : 0);  // to remove the extra padding in later sections.
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+  return [self heightForTableView:tableView content:[self contentForRowAtIndexPath:indexPath]];
+}
+
+#pragma mark - Helpers
+
+- (NSString *)contentForSectionHeader:(NSInteger)section {
+  return _keyPaths[section];
+}
+
+- (NSString *)contentForRowAtIndexPath:(NSIndexPath *)indexPath {
+  NSString *keyPath = _keyPaths[indexPath.section];
+  return [[[GIDSignIn sharedInstance].currentUser valueForKeyPath:keyPath] description];
+}
+
+- (CGFloat)heightForTableView:(UITableView *)tableView content:(NSString *)content {
+  CGSize constraintSize =
+      CGSizeMake(tableView.frame.size.width - 2 * kTableViewCellPadding, kVeryTallConstraint);
+  CGSize size;
+  UIFont *font = [UIFont systemFontOfSize:kTableViewCellFontSize];
+  NSDictionary *attributes = @{ NSFontAttributeName : font };
+  size = [content boundingRectWithSize:constraintSize
+                               options:0
+                            attributes:attributes
+                               context:NULL].size;
+  return size.height + kTableViewCellPadding;
+}
+
+@end
+

+ 54 - 0
Sample/Source/DataPickerState.h

@@ -0,0 +1,54 @@
+/*
+ * Copyright 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 <Foundation/Foundation.h>
+
+// Dictionary Key indicating whether multiple selection is enabled.
+extern NSString * const kMultipleSelectKey;
+// Dictionary Key for the array of elements to be shown.
+extern NSString * const kElementsKey;
+// Dictionary Key for the label of each element.
+extern NSString * const kLabelKey;
+// Dictionary Key for the short label for each element (Optional).
+extern NSString * const kShortLabelKey;
+// Dictionary Key to indicate whether a particular element should be selected by default (Optional).
+extern NSString * const kSelectedKey;
+
+// DataPickerState objects keep track of the list of available cells and set
+// of selected cells that are being used in a DataPickerViewController object.
+@interface DataPickerState : NSObject
+
+// An ordered list of cell labels (NSStrings) to select from
+@property(strong, nonatomic) NSArray *cellLabels;
+// A set of the labels of the selected cells (NSStrings).
+@property(strong, nonatomic) NSMutableSet *selectedCells;
+// Determines if multiple cells can be checked.
+@property(assign, nonatomic) BOOL multipleSelectEnabled;
+
+// Initializes a DataPickerState to collect its data from
+// the provided dictionary. The assumption about the provided
+// dictionary is that it obeys the structure:
+// dict[@"multiple-select"] - BOOL that represents whether multiple of the
+//                            elements can be simultaneously selected.
+// dict[@"elements"] - Array that contains the list of cell items to be shown.
+// dict[@"elements"][index] - Dictionary that contains properties for each cell.
+// dict[@"elements"][index][@"label"] - String storing the label of the cell.
+// dict[@"elements"][index][@"selected"] - BOOL for whether the cell begins as
+//                                         selected. If this property is not
+//                                         set, then we default to NO.
+- (id)initWithDictionary:(NSDictionary *)dict;
+
+@end

+ 59 - 0
Sample/Source/DataPickerState.m

@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 "DataPickerState.h"
+
+NSString * const kMultipleSelectKey = @"multiple-select";
+NSString * const kElementsKey = @"elements";
+NSString * const kLabelKey = @"label";
+NSString * const kShortLabelKey = @"shortLabel";
+NSString * const kSelectedKey = @"selected";
+
+@implementation DataPickerState
+
+- (id)initWithDictionary:(NSDictionary *)dict {
+  self = [super init];
+  if (self) {
+    _multipleSelectEnabled =
+        [[dict objectForKey:kMultipleSelectKey] boolValue];
+
+    NSMutableArray *cellLabels = [[NSMutableArray alloc] init];
+    NSMutableSet *selectedCells = [[NSMutableSet alloc] init];
+
+    NSArray *elements = [dict objectForKey:kElementsKey];
+    for (NSDictionary *elementDict in elements) {
+      NSMutableDictionary *cellLabelDict = [NSMutableDictionary dictionary];
+      NSString *label = [elementDict objectForKey:kLabelKey];
+      cellLabelDict[kLabelKey] = label;
+
+      if ([elementDict objectForKey:kShortLabelKey]) {
+        cellLabelDict[kShortLabelKey] = [elementDict objectForKey:kShortLabelKey];
+      }
+      [cellLabels addObject:cellLabelDict];
+
+      // Default selection mode is unselected, unless specified in plist.
+      if ([[elementDict objectForKey:kSelectedKey] boolValue]) {
+        [selectedCells addObject:label];
+      }
+    }
+
+    self.cellLabels = cellLabels;
+    self.selectedCells = selectedCells;
+  }
+  return self;
+}
+
+@end

+ 38 - 0
Sample/Source/DataPickerViewController.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 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 <UIKit/UIKit.h>
+
+@class DataPickerState;
+
+// This view controller controls a table view meant to select
+// options from a list. The list is supplied from the DataPickerDictionary.plist
+// file based upon what |dataKey| the controller is initialized with.
+@interface DataPickerViewController : UITableViewController
+
+// |dataState| stores the list of cells and the current set of selected cells.
+// It should be created and owned by whoever owns the DataPickerViewController,
+// so we only need a weak reference to it from here.
+@property(weak, readonly, nonatomic) DataPickerState *dataState;
+
+// This method initializes a DataPickerViewController using
+// a DataPickerState object, from which the view controller
+// obtains cell information for use in its table.
+- (id)initWithNibName:(NSString *)nibNameOrNil
+               bundle:(NSBundle *)nibBundleOrNil
+            dataState:(DataPickerState *)dataState;
+
+@end

+ 104 - 0
Sample/Source/DataPickerViewController.m

@@ -0,0 +1,104 @@
+/*
+ * Copyright 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 "DataPickerState.h"
+#import "DataPickerViewController.h"
+
+@implementation DataPickerViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil
+               bundle:(NSBundle *)nibBundleOrNil
+            dataState:(DataPickerState *)dataState {
+  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+  if (self) {
+    _dataState = dataState;
+  }
+  return self;
+}
+
+#pragma mark - Table view data source
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+  return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView
+    numberOfRowsInSection:(NSInteger)section {
+  return [self.dataState.cellLabels count];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+  static NSString * const kCellIdentifier = @"Cell";
+  UITableViewCell *cell =
+      [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
+
+  if (cell == nil) {
+    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
+                                  reuseIdentifier:kCellIdentifier];
+  }
+
+  NSDictionary *cellLabelDict = self.dataState.cellLabels[indexPath.row];
+  NSString *cellLabelText = cellLabelDict[kLabelKey];
+  if ([cellLabelDict objectForKey:kShortLabelKey]) {
+    cellLabelText = [cellLabelDict objectForKey:kShortLabelKey];
+  }
+  cell.textLabel.text = cellLabelText;
+  // If the cell is selected, mark it as checked
+  if ([self.dataState.selectedCells containsObject:cellLabelDict[kLabelKey]]) {
+    cell.accessoryType = UITableViewCellAccessoryCheckmark;
+  } else {
+    cell.accessoryType = UITableViewCellAccessoryNone;
+  }
+  return cell;
+}
+
+#pragma mark - Table view delegate
+
+- (void)tableView:(UITableView *)tableView
+    didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+  UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
+  NSDictionary *selectedCellDict = _dataState.cellLabels[indexPath.row];
+  NSString *label = selectedCellDict[kLabelKey];
+
+  if (self.dataState.multipleSelectEnabled) {
+    // If multiple selections are allowed, then toggle the state
+    // of the selected cell
+    if ([self.dataState.selectedCells containsObject:label]) {
+      [self.dataState.selectedCells removeObject:label];
+      selectedCell.accessoryType = UITableViewCellAccessoryNone;
+    } else {
+      [self.dataState.selectedCells addObject:label];
+      selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
+    }
+  } else {
+    // Set all cells to unchecked except for the one that was just selected
+    [self.dataState.selectedCells removeAllObjects];
+    [self.dataState.selectedCells addObject:label];
+
+    for (NSIndexPath *curPath in [self.tableView indexPathsForVisibleRows]) {
+      UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:curPath];
+      if (curPath.row == indexPath.row) {
+        cell.accessoryType = UITableViewCellAccessoryCheckmark;
+      } else {
+        cell.accessoryType = UITableViewCellAccessoryNone;
+      }
+    }
+  }
+  [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+}
+
+@end

+ 40 - 0
Sample/Source/LaunchScreen.xib

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB">
+            <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Google Sign-In" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+                    <rect key="frame" x="20" y="140" width="441" height="43"/>
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Sample App" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Npk-1c-nVk">
+                    <rect key="frame" x="168.5" y="204.5" width="144.5" height="24"/>
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
+                    <color key="textColor" red="0.40000000596046448" green="0.40000000596046448" blue="0.40000000596046448" alpha="1" colorSpace="calibratedRGB"/>
+                    <color key="highlightedColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+            <constraints>
+                <constraint firstAttribute="centerX" secondItem="Npk-1c-nVk" secondAttribute="centerX" constant="-0.5" id="8Hl-kO-KfB"/>
+                <constraint firstAttribute="centerY" secondItem="Npk-1c-nVk" secondAttribute="centerY" constant="23.5" id="J0S-6m-MK8"/>
+                <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="Kid-kn-2rF"/>
+                <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+                <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+            </constraints>
+            <nil key="simulatedStatusBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="404" y="445"/>
+        </view>
+    </objects>
+</document>

+ 51 - 0
Sample/Source/SignInViewController.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright 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 <UIKit/UIKit.h>
+
+@import GoogleSignIn;
+
+// A view controller for the Google Sign-In button which initiates a standard
+// OAuth 2.0 flow and provides an access token and a refresh token. A "Sign out"
+// button is provided to allow users to sign out of this application.
+@interface SignInViewController : UITableViewController <GIDSignInDelegate>
+
+@property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
+// A label to display the result of the sign-in action.
+@property(weak, nonatomic) IBOutlet UILabel *signInAuthStatus;
+// A label to display the signed-in user's display name.
+@property(weak, nonatomic) IBOutlet UILabel *userName;
+// A label to display the signed-in user's email address.
+@property(weak, nonatomic) IBOutlet UILabel *userEmailAddress;
+// An image view to display the signed-in user's avatar image.
+@property(weak, nonatomic) IBOutlet UIImageView *userAvatar;
+// A button to sign out of this application.
+@property(weak, nonatomic) IBOutlet UIButton *signOutButton;
+// A button to disconnect user from this application.
+@property(weak, nonatomic) IBOutlet UIButton *disconnectButton;
+// A button to inspect the authorization object.
+@property(weak, nonatomic) IBOutlet UIButton *credentialsButton;
+// A dynamically-created slider for controlling the sign-in button width.
+@property(weak, nonatomic) UISlider *signInButtonWidthSlider;
+
+// Called when the user presses the "Sign out" button.
+- (IBAction)signOut:(id)sender;
+// Called when the user presses the "Disconnect" button.
+- (IBAction)disconnect:(id)sender;
+// Called when the user presses the "Credentials" button.
+- (IBAction)showAuthInspector:(id)sender;
+
+@end

+ 452 - 0
Sample/Source/SignInViewController.m

@@ -0,0 +1,452 @@
+/*
+ * Copyright 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 "SignInViewController.h"
+
+@import GoogleSignIn;
+
+#import "AuthInspectorViewController.h"
+#import "DataPickerState.h"
+#import "DataPickerViewController.h"
+
+static NSString *const kSignInViewTitle = @"Sign-In Sample";
+static NSString *const kPlaceholderUserName = @"<Name>";
+static NSString *const kPlaceholderEmailAddress = @"<Email>";
+static NSString *const kPlaceholderAvatarImageName = @"PlaceholderAvatar.png";
+
+// Labels for the cells that have in-cell control elements.
+static NSString *const kGetUserProfileCellLabel = @"Get user Basic Profile";
+static NSString *const kButtonWidthCellLabel = @"Width";
+
+// Labels for the cells that drill down to data pickers.
+static NSString *const kColorSchemeCellLabel = @"Color scheme";
+static NSString *const kStyleCellLabel = @"Style";
+
+// Accessibility Identifiers.
+static NSString *const kCredentialsButtonAccessibilityIdentifier = @"Credentials";
+
+@implementation SignInViewController {
+  // This is an array of arrays, each one corresponding to the cell
+  // labels for its respective section.
+  NSArray *_sectionCellLabels;
+
+  // These sets contain the labels corresponding to cells that have various
+  // types (each cell either drills down to another table view, contains an
+  // in-cell switch, or contains a slider).
+  NSArray *_drillDownCells;
+  NSArray *_switchCells;
+  NSArray *_sliderCells;
+
+  // States storing the current set of selected elements for each data picker.
+  DataPickerState *_colorSchemeState;
+  DataPickerState *_styleState;
+
+  // Map that keeps track of which cell corresponds to which DataPickerState.
+  NSDictionary *_drilldownCellState;
+}
+
+#pragma mark - View lifecycle
+
+- (void)setUp {
+  _sectionCellLabels = @[
+    @[ kColorSchemeCellLabel, kStyleCellLabel, kButtonWidthCellLabel ],
+    @[ kGetUserProfileCellLabel ]
+  ];
+
+  // Groupings of cell types.
+  _drillDownCells = @[
+    kColorSchemeCellLabel,
+    kStyleCellLabel
+  ];
+
+  _switchCells =
+      @[ kGetUserProfileCellLabel ];
+  _sliderCells = @[ kButtonWidthCellLabel ];
+
+  // Initialize data picker states.
+  NSString *dictionaryPath =
+      [[NSBundle mainBundle] pathForResource:@"DataPickerDictionary"
+                                      ofType:@"plist"];
+  NSDictionary *configOptionsDict = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];
+
+  NSDictionary *colorSchemeDict = [configOptionsDict objectForKey:kColorSchemeCellLabel];
+  NSDictionary *styleDict = [configOptionsDict objectForKey:kStyleCellLabel];
+
+  _colorSchemeState = [[DataPickerState alloc] initWithDictionary:colorSchemeDict];
+  _styleState = [[DataPickerState alloc] initWithDictionary:styleDict];
+
+  _drilldownCellState = @{
+    kColorSchemeCellLabel :   _colorSchemeState,
+    kStyleCellLabel :         _styleState
+  };
+
+  // Make sure the GIDSignInButton class is linked in because references from
+  // xib file doesn't count.
+  [GIDSignInButton class];
+
+  GIDSignIn *signIn = [GIDSignIn sharedInstance];
+  signIn.shouldFetchBasicProfile = YES;
+  signIn.delegate = self;
+  signIn.presentingViewController = self;
+  [GIDSignIn sharedInstance].scopes = @[ @"email" ];
+}
+
+- (id)initWithNibName:(NSString *)nibNameOrNil
+               bundle:(NSBundle *)nibBundleOrNil {
+  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+  if (self) {
+    [self setUp];
+    self.title = kSignInViewTitle;
+  }
+  return self;
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self setUp];
+    self.title = kSignInViewTitle;
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.credentialsButton.accessibilityIdentifier = kCredentialsButtonAccessibilityIdentifier;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [self adoptUserSettings];
+  [self reportAuthStatus];
+  [self updateButtons];
+  [self.tableView reloadData];
+
+  [super viewWillAppear:animated];
+}
+
+#pragma mark - GIDSignInDelegate
+
+- (void)signIn:(GIDSignIn *)signIn
+    didSignInForUser:(GIDGoogleUser *)user
+           withError:(NSError *)error {
+  if (error) {
+    _signInAuthStatus.text = [NSString stringWithFormat:@"Status: Authentication error: %@", error];
+    return;
+  }
+  [self reportAuthStatus];
+  [self updateButtons];
+}
+
+- (void)signIn:(GIDSignIn *)signIn
+    didDisconnectWithUser:(GIDGoogleUser *)user
+                withError:(NSError *)error {
+  if (error) {
+    _signInAuthStatus.text = [NSString stringWithFormat:@"Status: Failed to disconnect: %@", error];
+  } else {
+    _signInAuthStatus.text = [NSString stringWithFormat:@"Status: Disconnected"];
+  }
+  [self reportAuthStatus];
+  [self updateButtons];
+}
+
+- (void)presentSignInViewController:(UIViewController *)viewController {
+  [[self navigationController] pushViewController:viewController animated:YES];
+}
+
+#pragma mark - Helper methods
+
+// Updates the GIDSignIn shared instance and the GIDSignInButton
+// to reflect the configuration settings that the user set
+- (void)adoptUserSettings {
+  // There should only be one selected color scheme
+  for (NSString *scheme in _colorSchemeState.selectedCells) {
+    if ([scheme isEqualToString:@"Light"]) {
+      _signInButton.colorScheme = kGIDSignInButtonColorSchemeLight;
+    } else {
+      _signInButton.colorScheme = kGIDSignInButtonColorSchemeDark;
+    }
+  }
+
+  // There should only be one selected style
+  for (NSString *style in _styleState.selectedCells) {
+    GIDSignInButtonStyle newStyle;
+    if ([style isEqualToString:@"Standard"]) {
+      newStyle = kGIDSignInButtonStyleStandard;
+      self.signInButtonWidthSlider.enabled = YES;
+    } else if ([style isEqualToString:@"Wide"]) {
+      newStyle = kGIDSignInButtonStyleWide;
+      self.signInButtonWidthSlider.enabled = YES;
+    } else {
+      newStyle = kGIDSignInButtonStyleIconOnly;
+      self.signInButtonWidthSlider.enabled = NO;
+    }
+    if (self.signInButton.style != newStyle) {
+      self.signInButton.style = newStyle;
+      self.signInButtonWidthSlider.minimumValue = [self minimumButtonWidth];
+    }
+    self.signInButtonWidthSlider.value = _signInButton.frame.size.width;
+  }
+}
+
+// Temporarily force the sign in button to adopt its minimum allowed frame
+// so that we can find out its minimum allowed width (used for setting the
+// range of the width slider).
+- (CGFloat)minimumButtonWidth {
+  CGRect frame = self.signInButton.frame;
+  self.signInButton.frame = CGRectZero;
+
+  CGFloat minimumWidth = self.signInButton.frame.size.width;
+  self.signInButton.frame = frame;
+
+  return minimumWidth;
+}
+
+- (void)reportAuthStatus {
+  GIDGoogleUser *googleUser = [[GIDSignIn sharedInstance] currentUser];
+  if (googleUser.authentication) {
+    _signInAuthStatus.text = @"Status: Authenticated";
+  } else {
+    // To authenticate, use Google Sign-In button.
+    _signInAuthStatus.text = @"Status: Not authenticated";
+  }
+
+  [self refreshUserInfo];
+}
+
+// Update the interface elements containing user data to reflect the
+// currently signed in user.
+- (void)refreshUserInfo {
+  if ([GIDSignIn sharedInstance].currentUser.authentication == nil) {
+    self.userName.text = kPlaceholderUserName;
+    self.userEmailAddress.text = kPlaceholderEmailAddress;
+    self.userAvatar.image = [UIImage imageNamed:kPlaceholderAvatarImageName];
+    return;
+  }
+  self.userEmailAddress.text = [GIDSignIn sharedInstance].currentUser.profile.email;
+  self.userName.text = [GIDSignIn sharedInstance].currentUser.profile.name;
+
+  if (![GIDSignIn sharedInstance].currentUser.profile.hasImage) {
+    // There is no Profile Image to be loaded.
+    return;
+  }
+  // Load avatar image asynchronously, in background
+  dispatch_queue_t backgroundQueue =
+      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+  __weak SignInViewController *weakSelf = self;
+
+  dispatch_async(backgroundQueue, ^{
+    NSUInteger dimension = round(self.userAvatar.frame.size.width * [[UIScreen mainScreen] scale]);
+    NSURL *imageURL =
+        [[GIDSignIn sharedInstance].currentUser.profile imageURLWithDimension:dimension];
+    NSData *avatarData = [NSData dataWithContentsOfURL:imageURL];
+
+    if (avatarData) {
+      // Update UI from the main thread when available
+      dispatch_async(dispatch_get_main_queue(), ^{
+        SignInViewController *strongSelf = weakSelf;
+        if (strongSelf) {
+          strongSelf.userAvatar.image = [UIImage imageWithData:avatarData];
+        }
+      });
+    }
+  });
+}
+
+// Adjusts "Sign in", "Sign out", and "Disconnect" buttons to reflect
+// the current sign-in state (ie, the "Sign in" button becomes disabled
+// when a user is already signed in).
+- (void)updateButtons {
+  BOOL authenticated = ([GIDSignIn sharedInstance].currentUser.authentication != nil);
+
+  self.signInButton.enabled = !authenticated;
+  self.signOutButton.enabled = authenticated;
+  self.disconnectButton.enabled = authenticated;
+  self.credentialsButton.hidden = !authenticated;
+
+  if (authenticated) {
+    self.signInButton.alpha = 0.5;
+    self.signOutButton.alpha = self.disconnectButton.alpha = 1.0;
+  } else {
+    self.signInButton.alpha = 1.0;
+    self.signOutButton.alpha = self.disconnectButton.alpha = 0.5;
+  }
+}
+
+#pragma mark - IBActions
+
+- (IBAction)signOut:(id)sender {
+  [[GIDSignIn sharedInstance] signOut];
+  [self reportAuthStatus];
+  [self updateButtons];
+}
+
+- (IBAction)disconnect:(id)sender {
+  [[GIDSignIn sharedInstance] disconnect];
+}
+
+- (IBAction)showAuthInspector:(id)sender {
+  AuthInspectorViewController *authInspector = [[AuthInspectorViewController alloc] init];
+  [[self navigationController] pushViewController:authInspector animated:YES];
+}
+
+- (IBAction)checkSignIn:(id)sender {
+  [self reportAuthStatus];
+}
+
+- (void)toggleBasicProfile:(UISwitch *)sender {
+  [GIDSignIn sharedInstance].shouldFetchBasicProfile = sender.on;
+}
+
+- (void)changeSignInButtonWidth:(UISlider *)sender {
+  CGRect frame = self.signInButton.frame;
+  frame.size.width = sender.value;
+  self.signInButton.frame = frame;
+}
+
+#pragma mark - UITableView Data Source
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+  return [_sectionCellLabels count];
+}
+
+- (NSInteger)tableView:(UITableView *)tableView
+ numberOfRowsInSection:(NSInteger)section {
+  return [_sectionCellLabels[section] count];
+}
+
+- (NSString *)tableView:(UITableView *)tableView
+    titleForHeaderInSection:(NSInteger)section {
+  if (section == 0) {
+    return @"Sign-In Button Options";
+  } else if (section == 1) {
+    return @"Other Options";
+  } else {
+    return nil;
+  }
+}
+
+- (BOOL)tableView:(UITableView *)tableView
+    shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
+  // Cells that drill down to other table views should be highlight-able.
+  // The other cells contain control elements, so they should not be selectable.
+  NSString *label = _sectionCellLabels[indexPath.section][indexPath.row];
+  if ([_drillDownCells containsObject:label]) {
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+  static NSString * const kDrilldownCell = @"DrilldownCell";
+  static NSString * const kSwitchCell = @"SwitchCell";
+  static NSString * const kSliderCell = @"SliderCell";
+
+  NSString *label = _sectionCellLabels[indexPath.section][indexPath.row];
+  UITableViewCell *cell;
+  NSString *identifier;
+
+  if ([_drillDownCells containsObject:label]) {
+    identifier = kDrilldownCell;
+  } else if ([_switchCells containsObject:label]) {
+    identifier = kSwitchCell;
+  } else if ([_sliderCells containsObject:label]) {
+    identifier = kSliderCell;
+  }
+
+  cell = [tableView dequeueReusableCellWithIdentifier:identifier];
+
+  if (cell == nil) {
+    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
+                                  reuseIdentifier:identifier];
+  }
+  // Assign accessibility labels to each cell row.
+  cell.accessibilityLabel = label;
+
+  if (identifier == kDrilldownCell) {
+    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+    DataPickerState *dataState = _drilldownCellState[label];
+    if (dataState.multipleSelectEnabled) {
+      cell.detailTextLabel.text = @"";
+    } else {
+      cell.detailTextLabel.text = [dataState.selectedCells anyObject];
+    }
+    cell.accessibilityValue = cell.detailTextLabel.text;
+  } else if (identifier == kSwitchCell) {
+    UISwitch *toggle = [[UISwitch alloc] initWithFrame:CGRectZero];
+
+    if ([label isEqualToString:kGetUserProfileCellLabel]) {
+      [toggle addTarget:self
+                    action:@selector(toggleBasicProfile:)
+          forControlEvents:UIControlEventValueChanged];
+      toggle.on = [GIDSignIn sharedInstance].shouldFetchBasicProfile;
+    }
+
+    toggle.accessibilityLabel = [NSString stringWithFormat:@"%@ Switch", cell.accessibilityLabel];
+    cell.accessoryView = toggle;
+  } else if (identifier == kSliderCell) {
+
+    UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 150, 0)];
+    slider.minimumValue = [self minimumButtonWidth];
+    slider.maximumValue = 268.0;
+    slider.value = self.signInButton.frame.size.width;
+    slider.enabled = self.signInButton.style != kGIDSignInButtonStyleIconOnly;
+
+    [slider addTarget:self
+                  action:@selector(changeSignInButtonWidth:)
+        forControlEvents:UIControlEventValueChanged];
+
+    slider.accessibilityIdentifier = [NSString stringWithFormat:@"%@ Slider", label];
+    self.signInButtonWidthSlider = slider;
+    cell.accessoryView = slider;
+    [self.signInButtonWidthSlider sizeToFit];
+  }
+
+  cell.textLabel.text = label;
+
+  return cell;
+}
+
+- (void)tableView:(UITableView *)tableView
+    didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+  [tableView deselectRowAtIndexPath:indexPath animated:YES];
+  UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
+  NSString *label = selectedCell.textLabel.text;
+
+  DataPickerState *dataState = [_drilldownCellState objectForKey:label];
+  if (!dataState) {
+    return;
+  }
+
+  DataPickerViewController *dataPicker =
+      [[DataPickerViewController alloc] initWithNibName:nil
+                                                 bundle:nil
+                                              dataState:dataState];
+  dataPicker.navigationItem.title = label;
+
+  // Force the back button title to be 'Back'
+  UIBarButtonItem *newBackButton =
+      [[UIBarButtonItem alloc] initWithTitle:@"Back"
+                                       style:UIBarButtonItemStylePlain
+                                      target:nil
+                                      action:nil];
+  [[self navigationItem] setBackBarButtonItem:newBackButton];
+  [self.navigationController pushViewController:dataPicker animated:YES];
+}
+
+@end

+ 101 - 0
Sample/Source/SignInViewController.xib

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SignInViewController">
+            <connections>
+                <outlet property="credentialsButton" destination="80" id="83"/>
+                <outlet property="disconnectButton" destination="65" id="71"/>
+                <outlet property="signInAuthStatus" destination="72" id="73"/>
+                <outlet property="signInButton" destination="bKH-Ji-uCR" id="aDr-fD-R3x"/>
+                <outlet property="signOutButton" destination="63" id="70"/>
+                <outlet property="userAvatar" destination="60" id="67"/>
+                <outlet property="userEmailAddress" destination="62" id="76"/>
+                <outlet property="userName" destination="61" id="75"/>
+                <outlet property="view" destination="55" id="56"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="55">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+            <nil key="simulatedStatusBarMetrics"/>
+            <view key="tableHeaderView" contentMode="scaleToFill" id="57">
+                <rect key="frame" x="0.0" y="0.0" width="320" height="197"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Status: Authenticated" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="72">
+                        <rect key="frame" x="21" y="67" width="280" height="21"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="PlaceholderAvatar.png" id="60">
+                        <rect key="frame" x="20" y="8" width="50" height="50"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    </imageView>
+                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="&lt;Name&gt;" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="61">
+                        <rect key="frame" x="78" y="8" width="153" height="21"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="&lt;Email&gt;" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" id="62">
+                        <rect key="frame" x="78" y="34" width="153" height="21"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="63">
+                        <rect key="frame" x="50" y="160" width="77" height="35"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
+                        <state key="normal" title="Sign out">
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="signOut:" destination="-1" eventType="touchUpInside" id="64"/>
+                        </connections>
+                    </button>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="65">
+                        <rect key="frame" x="186" y="160" width="97" height="35"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
+                        <state key="normal" title="Disconnect">
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="disconnect:" destination="-1" eventType="touchUpInside" id="66"/>
+                        </connections>
+                    </button>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="infoDark" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" id="80">
+                        <rect key="frame" x="168" y="68" width="22" height="22"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <connections>
+                            <action selector="showAuthInspector:" destination="-1" eventType="touchUpInside" id="82"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" id="bKH-Ji-uCR" customClass="GIDSignInButton">
+                        <rect key="frame" x="20" y="100" width="281" height="39"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <accessibility key="accessibilityConfiguration">
+                            <accessibilityTraits key="traits" button="YES"/>
+                        </accessibility>
+                    </view>
+                </subviews>
+                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+            </view>
+        </tableView>
+    </objects>
+    <resources>
+        <image name="PlaceholderAvatar.png" width="50" height="50"/>
+    </resources>
+</document>

+ 26 - 0
Sample/Source/main.m

@@ -0,0 +1,26 @@
+/*
+ * Copyright 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 <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char *argv[]) {
+  @autoreleasepool {
+    return UIApplicationMain(argc, argv, nil,
+        NSStringFromClass([AppDelegate class]));
+  }
+}