0

I have a really common problem trying to create spinning activity indicator during an user authentication task with Firebase

I tried to use CGD dispatch_async but that doesn't seem to handle my issue. Here is my code

    @IBAction func SignMeIn(sender: AnyObject) {
    ActivityIndicator.hidden = false
    ActivityIndicator.startAnimating()



        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
            NSLog("Before login func")
            self.logIn()

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                NSLog("After login func")
                self.ActivityIndicator.stopAnimating()
                self.ActivityIndicator.hidden = true
            })

        });
}

 func logIn(){
    myRootRef.authUser(TXT_User.text, password: TXT_Password.text,
        withCompletionBlock: { error, authData in
            if error != nil {
                NSLog(error.debugDescription)
            } else {
              NSLog("Connected !")
            }
    })


}

The thing is I surely do something wrong since in debug mode appears in this order :

"Before login func"
"After login func"
"Connected !" 

Whereas I should have

"Before login func"
"Connected !"
"After login func"

What am I doing wrong please ? Thank you very much for your help :) !

2 Answers 2

2

Your problem is that you have 2 async tasks 1. Login completion block 2. Activity indicator stop

If you want to stop activity indicator after the login process you should move the code in the completion block like this

@IBAction func SignMeIn(sender: AnyObject) {
    ActivityIndicator.hidden = false
    ActivityIndicator.startAnimating()

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
        NSLog("Before login func")
        self.logIn()
    });
}

func logIn(){
myRootRef.authUser(TXT_User.text, password: TXT_Password.text,
    withCompletionBlock: { error, authData in
        if error != nil {
            NSLog(error.debugDescription)
        } else {
          NSLog("Connected !")
        }

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            NSLog("After login func")
            self.ActivityIndicator.stopAnimating()
            self.ActivityIndicator.hidden = true
        })
})
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yes that's it !! Thank you so much !
2

The problem is that execution returns from logIn immediately, and not when the completion block is called.

To do what you need, you have to make the call to the main queue within the logIn completion handler - like this

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
        NSLog("Before login func")
        self.logIn()
 }

func logIn(){
    myRootRef.authUser(TXT_User.text, password: TXT_Password.text,
    withCompletionBlock: { error, authData in

        // success or fail, you need to stop the Activity Indicator
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                NSLog("After login func")
                self.ActivityIndicator.stopAnimating()
                self.ActivityIndicator.hidden = true
            })
        });

        if error != nil {
            NSLog(error.debugDescription)
        } else {
            NSLog("Connected !")
        }
    })
}

2 Comments

It's better to stop activity indicator no mater if there is an error because other way the user will be stuck with animated indicator
Thank you Russell ! I accepted Lachezar's answer but this one is also good !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.