0

Hi everyone I'm working with Firebase authentication with which I allow the user to log in with his email and a verification link that is sent to his email ...

Everything works but with iOS 13 I have to use SceneDelegate instead of AppDelegate and in the func scene method (_ scene: UIScene, continue userActivity: NSUserActivity) I get an alert that warns me that I am not calling the result of the flatMap call.

Can anyone help me resolve this alert?

Result of call to 'flatMap' is unused

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
     userActivity.webpageURL.flatMap(handlePasswordlessSignIn)
}

func handlePasswordlessSignIn(withURL: URL) -> Bool {
    let link = withURL.absoluteString

    if Auth.auth().isSignIn(withEmailLink: link) {

        guard let email = UserDefaults.standard.value(forKey: FirebaseUserAuthWithLink.email) as? String else {
            print("L'email utilizzata per accedere non esiste")
            return true
        }

        Auth.auth().signIn(withEmail: email, link: link) { (user, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            guard let user = user else {
                print(" Authentication con Link Fallita")
                return
            }
            let uid = user.user.uid
            print("Autenticazione Riuscita")

            let data = [
                "email" : email
            ] as [String : Any]

            Firestore.firestore().collection("Users").document(uid).setData(data) { (error) in
                if let error = error {
                    print(error.localizedDescription)
                    return
                }
            }
        }
        return true
    }
    return false
}

Following the tutorial for the implementation, all the examples of queues refer to AppDelegate instead I tried to update the code working on SceneDelegate

kAiN
  • 2,559
  • 1
  • 26
  • 54
  • What is that line of code intended to do? – matt Mar 19 '20 at 23:58
  • @matt I update my code... I make the call to Firebase to complete the authentication flow with email when the user receives the link on his email ... When he returns to the app he logs in – kAiN Mar 20 '20 at 00:06
  • @matt did I do something wrong? – kAiN Mar 20 '20 at 00:40
  • It's great but you haven't answered my question. What's the purpose of calling `flatMap` if all you want to do is call `handlePasswordlessSignIn`? Is it just supposed to be an elegant way of dealing with the fact that `userActivity.webpageURL` is an Optional. And now we have a new problem: What's the purpose of declaring `handlePasswordlessSignIn` to return a Bool? You are throwing away the result of `flatMap` _and_ you are throwing away the result of `handlePasswordlessSignIn`. – matt Mar 20 '20 at 00:51
  • @matt The problem is that from appDelegate to SceneDelegate I was unable to find an update for this code ... `passwordlessSignIn` verifying the authentication of my user in firebase therefore how could I make this part "right" without using `func scene (_ scene: UIScene, continue userActivity: NSUserActivity)`? – kAiN Mar 20 '20 at 00:54
  • No but I don't see how that's relevant. Your code would have the same result no matter where you said it. If the question is how to deal with the fact that `userActivity.webpageURL` might be Optional, use `if let`, that's what it's for. – matt Mar 20 '20 at 00:58

1 Answers1

1

You could rewrite like this:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    if let url = userActivity.webpageURL {
        handlePasswordlessSignIn(withURL:url)
    }
}

But then you will still get a complaint, because now you are ignoring the result of handlePasswordlessSignIn! You can solve that by designating handlePasswordlessSignIn as being @discardableResult:

@discardableResult
func handlePasswordlessSignIn( //...
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • It was just that !! @discardableResult was very helpful! Thanks a lot you were really very kind – kAiN Mar 20 '20 at 01:03
  • 1
    @kAiN While this answer is correct, it's kind of a workaround to a core problem with code in the question. This `Auth.auth().signIn(withEmail:` is an asynchronous function and that means any code following the closure, like `return true` will execute *before* the code within the closure. In this case, your function will return true every time. This answer shows how to ignore the return, but you really shouldn't do that in the first place. The correct flow would be within the closure, once the user is auth'd, you should proceed to the next step; e.g. show the next viewController for example. – Jay Mar 20 '20 at 17:53
  • @Jay I totally agree. That’s why I asked why the OP is returning a value from a function that does asynchronous networking. But I couldn’t get an answer. – matt Mar 20 '20 at 17:57