GrayFox
GrayFox

Reputation: 814

How to set UIActivityIndicator async

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 :) !

Upvotes: 0

Views: 125

Answers (2)

Lachezar Todorov
Lachezar Todorov

Reputation: 923

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
        })
})
}

Upvotes: 2

Russell
Russell

Reputation: 5554

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 !")
        }
    })
}

Upvotes: 2

Related Questions