SwiftUIでFireBaseのGoogleログイン機能

## 2日もかかったのでメモとして残しておきます
### 今回はCocoaPods の使用は必要ありませんでした

#### `「File」`→`「Adding package dependencies」`からインストールするだけで大丈夫でした

## AppDelegate.swift
```
import SwiftUI
import Firebase

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    FirebaseApp.configure()

    return true
  }
}
```
# firebase_testApp.swift
```
import SwiftUI
import Firebase

@main
struct firebase_testApp: App {
    // register app delegate for Firebase setup
      @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

```

```

import SwiftUI
import Firebase
import FirebaseAuth
import GoogleSignIn


struct ContentView: View {
    @State private var isSignedIn = false
    @State private var userName: String = ""
    @State private var userEmail: String = ""
    @State private var profileImage: UIImage? = nil

    var body: some View {
        VStack(spacing: 20) {
            if isSignedIn {
                VStack {
                    if let profileImage = profileImage {
                        Image(uiImage: profileImage)
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 100, height: 100)
                            .clipShape(Circle())
                            .overlay(Circle().stroke(Color.blue, lineWidth: 2))
                            .shadow(radius: 5)
                    }

                    Text("Welcome, \(userName)")
                        .font(.title2)
                        .bold()

                    Text(userEmail)
                        .font(.subheadline)
                        .foregroundColor(.gray)

                    Button("Sign Out") {
                        signOut()
                    }
                    .frame(width: 200, height: 50)
                    .background(Color.red)
                    .foregroundColor(.white)
                    .cornerRadius(10)
                }
            } else {
                VStack {
                    GoogleSignInButton {
                        signInWithGoogle()
                    }
                }
            }
        }
        .padding()
    }

    private func signInWithGoogle() {
        guard let clientID = FirebaseApp.app()?.options.clientID else { return }

        let config = GIDConfiguration(clientID: clientID)
        guard let rootViewController = UIApplication.shared.connectedScenes
            .compactMap({ $0 as? UIWindowScene })
            .flatMap({ $0.windows })
            .first(where: { $0.isKeyWindow })?.rootViewController else {
            print("Unable to get root view controller.")
            return
        }

        GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController) { result, error in
            if let error = error {
                print("Google Sign-In failed: \(error.localizedDescription)")
                return
            }

            guard let user = result?.user,
                  let idToken = user.idToken?.tokenString else { return }

            let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: user.accessToken.tokenString)
            Auth.auth().signIn(with: credential) { authResult, error in
                if let error = error {
                    print("Firebase Authentication failed: \(error.localizedDescription)")
                } else {
                    self.isSignedIn = true
                    self.userName = user.profile?.name ?? "No Name"
                    self.userEmail = user.profile?.email ?? "No Email"
                    
                    // Load profile image
                    if let imageURL = user.profile?.imageURL(withDimension: 200) {
                        loadProfileImage(from: imageURL)
                    }
                }
            }
        }
    }

    private func signOut() {
        do {
            try Auth.auth().signOut()
            GIDSignIn.sharedInstance.signOut()
            self.isSignedIn = false
            self.userName = ""
            self.userEmail = ""
            self.profileImage = nil
        } catch {
            print("Failed to sign out: \(error.localizedDescription)")
        }
    }

    private func loadProfileImage(from url: URL) {
        URLSession.shared.dataTask(with: url) { data, _, error in
            if let error = error {
                print("Failed to load profile image: \(error.localizedDescription)")
                return
            }

            if let data = data, let image = UIImage(data: data) {
                DispatchQueue.main.async {
                    self.profileImage = image
                }
            }
        }.resume()
    }
}

// MARK: - Google Sign-In Button
struct GoogleSignInButton: View {
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            HStack {
                Image(systemName: "g.circle.fill")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 30, height: 30)
                    .foregroundColor(.white)

                Text("Sign in with Google")
                    .fontWeight(.semibold)
                    .font(.system(size: 18))
            }
            .frame(width: 250, height: 50)
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(25)
        }
        .shadow(radius: 5)
    }
}

#Preview {
    ContentView()
}
```

### firebase-test-Info.plist の例 
```
<?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>CFBundleName</key>
    <string>バンドルID</string>
    <key>CFBundleIdentifier</key>
    <string>com.example.アプリ名</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>arm64</string>
    </array>
    <key>UIDeviceFamily</key>
    <array>
        <integer>1</integer>
        <integer>2</integer>
    </array>
    
    <!-- Google Sign-In 用の URL スキーム -->
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>com.googleusercontent.apps.10*******-*******</string>
            </array>
        </dict>
    </array>
    
    <!-- Google Sign-In 用の GIDClientID -->
    <key>GIDClientID</key>
    <string>10*******-*******.apps.googleusercontent.com</string>
</dict>
</plist>
```

### ポイント　以下の２つの値が一致していること
```
<key>GIDClientID</key>
<string>10*******-*******.apps.googleusercontent.com</string>
```

```
<key>CFBundleURLSchemes</key>
<array>
        <string>com.googleusercontent.apps.10*******-*******</string>
</array>
```


## 以下CocoaPods のコマンドは必要ありません
>Profileファイルの生成コマンド
```
pod init
```

>Profileファイルの記述例
```
# Uncomment the next line to define a global platform for your project
platform :ios, '16.0'


target 'プロジェクト名' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'FirebaseCore'
  pod 'Firebase/Auth'
  pod 'GoogleSignIn'
  ...以下省略

end

```

Profileファイルの記述後にインストールコマンド
```
pod install
```