Search code examples
iosswiftseguealamofire

viewDidLoad() is running before Alamofire request in prepareforsegue has a chance to finish


I have two viewControllers that are giving me trouble. One is called notificationAccessViewController.swift and the other is called classChooseViewController.swift. I have a button in the notificationAccessViewController that triggers a segue to the classChooseViewController. What I need to do is within the prepareForSegue function, perform an Alamofire request and then pass the response to the classChooseViewController. That works! BUT, not fast enough.

Below is my prepareForSegue function within the notificationAccessViewController

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let DestViewController = segue.destination as! classChooseViewController
    Alamofire.request("MYURL.com").responseJSON { (response) in
        if let JSON : NSDictionary = response.result.value as! NSDictionary?{
            let classNameArray = JSON["className"] as! NSArray
            print("---")
            print(classNameArray)
            DestViewController.classNameArray = classNameArray
        }
    }
}

I have it printing out classNameArray to the console, which it does SUCCESSFULLY. Although, in my classChooseViewController.swift, I also print out the classNameArray to the console and it prints with nothing inside of it. This is because the viewDidLoad() function of the classChooseViewController.swift is running before the prepareForSegue function has finished. I want to know what I can do to ensure that the classChooseViewController does not load until the prepareForSegue function has FINISHED running.

Below is my code for classChooseViewController

class classChooseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var classNameArray: NSArray = []
    override func viewDidLoad() {
        super.viewDidLoad()
        print(classNameArray)
    }
}

I have attached a picture of what the console reads. You can see that the classNameArray prints from the classChooseViewControllers viewDidLoad() function BEFORE the prepareForSegue() function because the "---" prints out after.

Console Printout Screenshot


Solution

  • Your design is wrong.

    The Alamofire request function is asynchronous. It returns immediately, before the results are ready. Then it invokes the completion handler that you pass in.

    I tend to agree with Paul that you should make the request in the destination view controller, not in the current view controller.

    If you DO want to fetch the data in Alamofire before you segue to the other view controller then you'll need to write a method that starts the request, then invokes the segue to the other view controller from the Alamofire.request() call's completion handler.

    If you're invoking the new view controller from a button press, you need to not link the button directly to a segue, but instead write an IBAction method that triggers the AlamoFire request call, then invokes the segue (or instantiates the view controller directly and pushes/presents it manually) from the completion handler.

    Something like this:

    @IBAction buttonAction(sender: UIButton) {
      Alamofire.request("MYURL.com").responseJSON { 
        (response) in
        if let JSON : NSDictionary = response.result.value as! NSDictionary? {
          let classNameArray = JSON["className"] as! NSArray
            print("---")
            print(classNameArray)
            let theClassChooseViewController = storyboard.instantiateViewController(withIdentifier:"ClassChooseViewController" as ClassChooseViewController
            theClassChooseViewController.classNameArray = classNameArray
            presentViewController(theClassChooseViewController, 
              animated: true,
              completion: nil)
         }
      }
    }
    

    By the way, class names and types should start with an upper case letter, and variable names should start with a lower-case letter. This is a very strong convention in both Swift and Objective-C, and you'll confuse the hell out of other iOS/Mac developers unless you follow the convention.