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