SwiftUIからFirebaseUIを使う

3 min read読了の目安(約2800字 2

SwiftUIでFirebaseUIを使いました。動作画面はこちらです。

FirebaseUI は Firebase Authentication の認証機能を簡単に利用することができるライブラリです。

https://firebase.google.com/docs/auth/web/firebaseui?hl=ja

FirebaseUIはUIKitのライブラリのためSwiftUIからはそのままでは使えないようです、
SwiftUIから使用するための記事があったのでそちらを参考にしました。

https://qiita.com/From_F/items/5888c548a9a41232509f

FirebaseUIView

UIViewControllerをSwiftUIから使用するためにはUIViewControllerRepresentableでラップします。

FirebaseUIView.swift
import SwiftUI
import FirebaseUI

struct FirebaseUIView: UIViewControllerRepresentable {
    typealias UIViewControllerType = UINavigationController

    class Coordinator: NSObject, FUIAuthDelegate {
        let parent: FirebaseUIView
        init(_ parent: FirebaseUIView) {
            self.parent = parent
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIViewController(context: Context) -> UINavigationController {
        let authUI = FUIAuth.defaultAuthUI()!
        let providers: [FUIAuthProvider] = [
            FUIGoogleAuth(authUI: authUI),
        ]
        authUI.providers = providers
        authUI.delegate = context.coordinator
        return authUI.authViewController()
    }

    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {

    }
}

FirebaseAuthStateObserver

Firebase Authのステートをハンドリングするためのクラスです。

FirebaseAuthStateObserver.swift
import Firebase

class FirebaseAuthStateObserver: ObservableObject {
    @Published var isSignin: Bool = false
    private var listener: AuthStateDidChangeListenerHandle!

    init() {
        listener = Auth.auth().addStateDidChangeListener { (auth, user) in
            if let _ = user {
                print("sign-in")
                self.isSignin = true
            } else {
                print("sign-out")
                self.isSignin = false
            }
        }
    }

    deinit {
        Auth.auth().removeStateDidChangeListener(listener)
    }

}

ContentView

呼び出す側は以下のように実装しました。

ContentView.swift
import SwiftUI
import Firebase

struct ContentView: View {
    @ObservedObject private var authState = FirebaseAuthStateObserver()
    @State var isShowSheet = false

    var body: some View {
        VStack {
            if authState.isSignin {
                Text("You are logined.")
                    .padding()
                Button("logout") {
                    try! Auth.auth().signOut()
                }
            }
            else {
                Text("You are not logged in.")
                    .padding()
                Button("login") {
                    isShowSheet.toggle()
                }
            }
        }
        .sheet(isPresented: $isShowSheet, content: {
            FirebaseUIView()
        })
    }
}