What to Update on MainQueue while running Async Call

Viewed 331

I send some info to Firebase and 5 things can happen in the callback if successful or 3 things can happen if unsuccessful:

If successful:

  1. the activity indicator is dismissed

  2. a class level variable with the date updates

  3. an alert appears with a message that includes that variable

  4. a push is performed to another vc

  5. the sendButton is enabled again (it's disabled once they press it)

If UnSuccessful:

  1. the activity indicator is dismissed

  2. an alert appears with a message that says it's unsuccessful

  3. the sendButton is enabled again (it's disabled once they press it)

When I tried to put the navigationController?.pushViewController on the mainQueue there was always problems with it specifically it didn't always perform.

//caused problems
DispatchQueue.main.async {
         navigationController?.pushViewController(nextVC, animated: false)
            }

Once I took it off and left it in the background it ran perfectly fine. I know I should update the alert but what about the class level variable that the alert uses and dismissing activity indicator?

Firebase Code:

@IBOutlet weak fileprivate var sendButton: UIButton!

let date = Date() //formatted in viewDidLoad
var todaysDate = ""
let activityIndicator = UIActivityIndicatorView() //formatted in viewDidLoad

@IBAction fileprivate func sendButtonTapped(_ sender: UIButton){

sendButton.isEnabled = false
view.addSubview(activityIndicator)

//dict has some values

nextVCRef?.updateChildValues(dict, withCompletionBlock: {
            (error, ref) in

            if error != nil{

              DispatchQueue.main.async {
                self.activityIndicator.removeFromSuperView
                self.alertError()
                self.sendButton.isEnabled = true//i normally would put this is the alertError action but for clarity i put it here
              }
              return
            }

            DispatchQueue.main.async {
                self.todaysDate = self.date
                self.alertSuccessful()//everything happens in the function
            }
        })
}

fileprivate alertSuccessful(){
        self.activityIndicator!.removeFromSuperView
        let alert = UIAlertController(title: "Thank You!", message: "Today's date is \(self.todaysDate).", preferredStyle: UIAlertControllerStyle.alert)
        let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){
            (action) in
            self.sendButton.isEnabled = true
            _ = self.navigationController?.pushViewController(nextVC, animated: false)
        }
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
}

fileprivate alertError(){
        let alert = UIAlertController(title: "Unknown Error!", message: "There was an error. Try again.", preferredStyle: UIAlertControllerStyle.alert)
        let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
    }
}

The question is between the variable being set, activity indicator being dismissed, the alert appearing, sendButton being re-enabled, and a push being performed, what should and shouldn't be on the main queue?

Btw I didn't need to update the date variable in the background but in another scenario I might pull some info from Firebase and the variable would be updated in the callback. I didn't include that code and used this instead because the main point is should the class variable get updated on the mainqueue in the background thread?

1 Answers
Related