# #swift #firebase #swiftui #google-signin
Вопрос:
Я пытаюсь настроить последний гугл-дизайн с помощью SwiftUI. Официальная документация Firebase предлагает устаревший подход, разработанный для UIKit, ViewControllers и AppDelegate, поэтому просто невозможно узнать, какой обходной путь необходим для его работы. Я смог реализовать UIApplicationDelegateAdaptor, чтобы получить доступ к методу didFinishLaunchingWithOptions для настройки FirebaseApp и GIDSignIn. Следуя этой документации: https://firebase.google.com/docs/auth/ios/google-signin В конечном счете я остановился на шаге 4. Неясно, где я должен использовать этот код или как интегрировать его в парадигму SwiftUI:
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID)
// Start the sign in flow!
GIDSignIn.sharedInstance.signIn(with: config, presenting: self) { [unowned self] user, error in
if let error = error {
// ...
return
}
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
// ...
}
Я знаю об этом руководстве от Google: https://developers.google.com/identity/sign-in/ios/quick-migration-guide но нет примера кода, показывающего, как это сделать правильно.
Ответ №1:
Вероятно, вы захотите запустить этот код в результате действия, которое выполняет пользователь. Button
Например , после нажатия кнопки «а».
Хитрая часть будет заключаться в том, что GIDSignIn.sharedInstance.signIn
UIViewController
для своего presenting
аргумента требуется a, что не обязательно просто получить в SwiftUI. Вы можете использовать a UIViewControllerRepresentable
, чтобы получить ссылку на контроллер представления в иерархии, из которой вы можете представить.
class LoginManager : ObservableObject {
var viewController : UIViewController?
func runLogin() {
guard let viewController = viewController else {
fatalError("No view controller")
}
//Other GIDSignIn code here. Use viewController for the `presenting` argument
}
}
struct DummyViewController : UIViewControllerRepresentable {
var loginManager : LoginManager
func makeUIViewController(context: Context) -> some UIViewController {
let vc = UIViewController()
loginManager.viewController = vc
return vc
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
struct ContentView : View {
@StateObject private var loginManager = LoginManager()
var body: some View {
VStack(spacing: 0) {
Button(action: {
loginManager.runLogin()
}) {
Text("Login")
DummyViewController(loginManager: loginManager)
.frame(width: 0, height: 0)
}
}
}
}
Комментарии:
1. Спасибо за быстрый ответ! Насколько я понимаю, в моем случае нет другого способа, кроме как использовать uiviewcontrollerпредставляемый?
2. Вы также можете попытаться получить ссылку на контроллер представления из
window
, но это может быть проблематично в современных приложениях на основе сцен, где не обязательно одно окно. Другой вариант-использовать что-то вроде SwiftUI-Introspect, но лично я предпочел бы использовать uiviewcontrollerпредставляемый, чем вводить зависимость от третьей стороны.