0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftUIでFireBaseのGoogleログイン機能

Posted at

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>

ポイント 以下の2つの値が一致していること

<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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?