如何在Compose Multiplatform中实现iOS端Firebase谷歌认证
Compose Multiplatform(2023新方案)iOS端Firebase谷歌认证实现(Swift配合Kotlin)
前置准备
- 完成iOS项目的Firebase基础配置:导入
GoogleService-Info.plist,在Podfile中添加pod 'Firebase/Auth'和pod 'GoogleSignIn'并执行pod install - 确保Compose Multiplatform项目的iosMain模块已正确关联Xcode项目
1. Common层定义Expect接口
在commonMain目录下定义跨平台的认证抽象类,统一调用入口:
expect class FirebaseAuthManager { suspend fun signInWithGoogle(): Result<String> // 返回用户ID或错误信息 fun signOut() }
2. Xcode中编写Swift桥接逻辑
在Xcode项目中创建以下文件,处理iOS系统层的谷歌认证流程:
2.1 认证逻辑实现(FirebaseAuthBridge.swift)
import FirebaseAuth import GoogleSignIn import UIKit @objc class FirebaseAuthBridge: NSObject { static let shared = FirebaseAuthBridge() private override init() {} func signInWithGoogle(completion: @escaping (String?, Error?) -> Void) { guard let clientID = FirebaseApp.app()?.options.clientID else { completion(nil, NSError(domain: "Firebase", code: -1, userInfo: [NSLocalizedDescriptionKey: "Firebase未完成配置"])) return } let config = GIDConfiguration(clientID: clientID) guard let rootVC = UIApplication.shared.windows.first?.rootViewController else { completion(nil, NSError(domain: "UI", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取根视图控制器"])) return } GIDSignIn.sharedInstance.signIn(with: config, presenting: rootVC) { user, error in if let error = error { completion(nil, error) return } guard let auth = user?.authentication, let idToken = auth.idToken else { completion(nil, NSError(domain: "GoogleSignIn", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取ID Token"])) return } let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: auth.accessToken) Auth.auth().signIn(with: credential) { authResult, error in completion(authResult?.user.uid, error) } } } func signOut() { do { try Auth.auth().signOut() GIDSignIn.sharedInstance.signOut() } catch { print("登出失败: \(error.localizedDescription)") } } }
2.2 桥接头文件(FirebaseAuthBridge-Bridging-Header.h)
让Kotlin能识别Swift类的接口:
#import <Foundation/Foundation.h> @interface FirebaseAuthBridge : NSObject + (instancetype)shared; - (void)signInWithGoogleWithCompletion:(void (^)(NSString * _Nullable, NSError * _Nullable))completion; - (void)signOut; @end
然后在Xcode的Build Settings中,将Objective-C Bridging Header设置为该文件的路径(例如$(PROJECT_DIR)/FirebaseAuthBridge-Bridging-Header.h)
3. iOS层实现Actual类
在iosMain目录下编写Kotlin代码,通过Kotlin/Native interop调用Swift桥接类:
import kotlinx.coroutines.suspendCancellableCoroutine import platform.Foundation.NSError import platform.darwin.dispatch_async import platform.darwin.dispatch_get_main_queue import kotlin.coroutines.resume actual class FirebaseAuthManager { private val authBridge = FirebaseAuthBridge.shared() actual suspend fun signInWithGoogle(): Result<String> = suspendCancellableCoroutine { continuation -> // 必须切换到主线程执行UI操作 dispatch_async(dispatch_get_main_queue()) { authBridge.signInWithGoogleWithCompletion { userId, error -> when { error != null -> continuation.resume(Result.failure(Exception(error.localizedDescription))) userId != null -> continuation.resume(Result.success(userId)) else -> continuation.resume(Result.failure(Exception("登录失败,未获取到用户ID"))) } } } } actual fun signOut() { dispatch_async(dispatch_get_main_queue()) { authBridge.signOut() } } }
4. Common层Compose代码调用
在跨平台UI中直接调用认证逻辑,无需区分平台:
import androidx.compose.foundation.layout.Column import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.coroutines.launch @Composable fun AuthScreen() { val lifecycleScope = rememberCoroutineScope() Column { Button(onClick = { lifecycleScope.launch { val result = FirebaseAuthManager().signInWithGoogle() when (result) { is Result.Success -> { // 处理登录成功逻辑,如跳转主页、保存用户信息 } is Result.Failure -> { // 处理错误,如显示Toast } } } }) { Text("谷歌登录") } Button(onClick = { FirebaseAuthManager().signOut() }) { Text("登出") } } }
关键排坑点
- 所有涉及iOS UI的操作必须在主线程执行,否则会崩溃,需用
dispatch_async(dispatch_get_main_queue())切换 - 确保iOS项目的Info.plist中添加了谷歌登录的URL Scheme,格式为
com.googleusercontent.apps.${你的Firebase Client ID} - 检查Pod依赖版本是否匹配,避免因版本冲突导致的认证失败
内容的提问来源于stack exchange,提问作者Lucas Kim
相关产品推荐
相关产品推荐

