swiftuifbsdkloginkit

Facebook Login + SwiftUI: loginButton & loginButtonDidLogOut are NOT called after login/logout


I'm trying to implement Facebook login for me SwiftUI app and here's my AppDelegate.swift file:

import UIKit
import FirebaseCore
import FirebaseAuth
import FBSDKLoginKit
import FBSDKCoreKit

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, LoginButtonDelegate {

    static var orientationLock = UIInterfaceOrientationMask.portrait

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return AppDelegate.orientationLock
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()

        return ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    @available(iOS 9.0, *)
    func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any])
        -> Bool {

            let handled = ApplicationDelegate.shared.application(
                application,
                open: url,
                sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
                annotation: options[UIApplication.OpenURLOptionsKey.annotation]
            )

            return handled

    }

    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

        return ApplicationDelegate.shared.application(
            application,
            open: url
        )
    }

    func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {
        print("FB Login Button function")
        if let error = error {
            print("ERROR1: \(error.localizedDescription)")
            return
        }

        let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)

        Auth.auth().signIn(with: credential) { (res, err) in
            if err != nil {
                print("ERROR2: \(String(describing: err?.localizedDescription))")
                return
            }

            print("email: \(String(describing: res?.user.email))")
            print("name: \(String(describing: res?.user.displayName))")
        }

    }

    func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
        print("Did logout")
    }

Ok, here comes my SwiftUI code:

import SwiftUI
import FirebaseCore
import FBSDKLoginKit

struct LoginView: View {
    @EnvironmentObject var thisSession: CurrentSession
    @ObservedObject var mainData = MainViewModel()

    var body: some View {
        VStack {
            facebook().frame(width: 240, height: 50)
        }
    }
}

struct LoginView_Previews: PreviewProvider {
    static var previews: some View {
        LoginView().environmentObject(CurrentSession())
    }
}

struct facebook : UIViewRepresentable {

    func makeUIView(context: UIViewRepresentableContext<facebook>) -> FBLoginButton {

        let button = FBLoginButton()
        //button.delegate = self
        return button
    }
    func updateUIView(_ uiView: FBLoginButton, context: UIViewRepresentableContext<facebook>) {
        print("FBButton updateUIView called")
    }
}

I can see the button on my LoginView and i even can login/logout (the text on the button changes respectively from "Login" to "Log out"... But the code from "loginButton" and "loginButtonDidLogOut" is never executed. I was supposed to see some messages in my debug console but this code just is not called.

Am I doing something wrong? Seems like i forgot to set some delegate or i should call Auth.auth() somewhere else instead of loginButton() function..


Solution

  • Your AppDelegate conforms to LoginButtonDelegate, so you only need to set the delegate within the makeUIView:

    func makeUIView(context: UIViewRepresentableContext<facebook>) -> FBLoginButton {
        let button = FBLoginButton()
        button.delegate = UIApplication.shared.delegate as! AppDelegate
        return button
    }