iosasynchronousalamofireswift5alamofire-request

Alamofire 5 swift 5 wait for the result of the alamofire query to show the initial view


The current situation is I have an initial view of login (A) and a second view when (B) has already logged in.

I want that when I open the application and the user has the values stored in the UserDefaults.standard, check that the values match those of the server and if they are correct enter the B view.

The problem is that alamofire is asynchronous, and the A-view is loaded before you get the answer.

SceneDelegate.swift

First attempt before we knew that alamofire was launched asynchronously

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

   //Code to open default viewA
   ...

   //Code to try open viewB
    let logAcepted = openViewB(url, param)
    if logAcepted //<-- this execute before query in func before
     {
       if let windowScene = scene as? UIWindowScene 
        {
            let window = UIWindow(windowScene: windowScene)
             window.rootViewController = UIHostingController(rootView: Principal())
             self.window = window
             window.makeKeyAndVisible()
         }
     }
}

I have seen that there is a completion field that could help to solve this problem but I think that I have not applied it well.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

   //Code to open default viewA
   ...

   //Code to try open viewB
   openViewB(url, param, completion: {logAcepted in
        if logAcepted 
        {
              if let windowScene = scene as? UIWindowScene 
              {
                 let window = UIWindow(windowScene: windowScene)
                  window.rootViewController = UIHostingController(rootView: Principal())
                  self.window = window
                   window.makeKeyAndVisible()
               }
         }
      })
 }

How can I make this function run synconically? or have the main code wait for the result of the query?

func openViewB(_ url: String, _ param: [String : String], completion : @escaping (Bool)->())  {
    var ret : Bool = false
    AF.request(url, parameters:  param).responseJSON {response in
        switch response.result {
            case .success(let value):
                if let JSON = value as? [String: Any]
                {
                    let status = JSON["status"] as! String
                    switch status
                    {
                        case "Ok":
                            ret =  true
                            completion(ret)
                        default:
                            ret = false
                            completion(ret)
                    }
                }
            case .failure( _):
                ret = false
                completion(ret)
        }
    }
}

I found a lot of related information but none that works in this version of swift/alamofire


Solution

  • Don't wait, never wait.

    Your openViewB method has already a completion handler, use it.

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
        //Code to open default viewA
        ...
    
        //Code to try open viewB
        openViewB(url, param) { logAccepted in
            if logAccepted
            {
                if let windowScene = scene as? UIWindowScene 
                {
                    let window = UIWindow(windowScene: windowScene)
                     window.rootViewController = UIHostingController(rootView: Principal())
                     self.window = window
                     window.makeKeyAndVisible()
                 }
             }
        }
    }