首页 > 解决方案 > Swift async call and return

问题描述

func sendPalletCheckScanAsUrl(viewController: UIViewController?, palletNr: String) -> PalletCheckHelper.PalletCheckerResponse  {
            var palletCheckerResponse = PalletCheckHelper.PalletCheckerResponse()
            var urlComponents = URLComponents()
            urlComponents = JsonHelper.defineUrlComponents() //this components are common for all requests
            urlComponents.path = "/Inventory/GetPalletDetail/OP"
            
            do {
                
                urlComponents.queryItems = [
                    URLQueryItem(name: "id", value: palletNr)
                ]
            } catch {
                //TODO:error handling
            }
            
            guard let url = urlComponents.url else { fatalError("Could not create URL from components") }
            
            // Specify this request as being a POST method
            var req = URLRequest(url: url)
            req.httpMethod = "GET"
            
            // Make sure that we include headers specifying that our request's HTTP body; this is done by helper function
            req = JsonHelper.defineCommonHeaders(request: req)
            print (req)
            
            
            JsonHelper.configSessionAndSendPalletNr(request: req) {
                returned in
                palletCheckerResponse = returned
                print ("returned JSON INSIDE", palletCheckerResponse)
            }
            
            print ("returned JSON OUTSIDE", palletCheckerResponse)
            
            return palletCheckerResponse
          }
    }

Something wrong here with async calls. calling

JsonHelper.configSessionAndSendPalletNr(request: req) gives me proper JSON sttring (print JSON INSIDE and all singing and dancing). Assigning returned to variable and printing outside is empty.

returned JSON OUTSIDE PalletCheckerResponse(deliveryId: nil, bookedDate: nil, onSiteDateTime: nil, companyName: nil)

returned JSON INSIDE PalletCheckerResponse(deliveryId: Optional("D113789"), bookedDate: Optional("2019-06-26T09:00:00"), onSiteDateTime: Optional("2019-06-26T10:33:23"), companyName: Optional("Omega"))

What am I missing?

标签: iosswiftasynchronous

解决方案


This is how your method should look like

func sendPalletCheckScanAsUrl(viewController: UIViewController?, palletNr: String, completionHandler : @escaping (PalletCheckHelper.PalletCheckerResponse) -> Void) {
    
    var palletCheckerResponse = PalletCheckHelper.PalletCheckerResponse()
    var urlComponents = URLComponents()
    urlComponents = JsonHelper.defineUrlComponents() //this components are common for all requests
    urlComponents.path = "/Inventory/GetPalletDetail/OP"
    
    do {
        
        urlComponents.queryItems = [
            URLQueryItem(name: "id", value: palletNr)
        ]
    } catch {
        //TODO:error handling
    }
    
    guard let url = urlComponents.url else { fatalError("Could not create URL from components") }
    
    // Specify this request as being a POST method
    var req = URLRequest(url: url)
    req.httpMethod = "GET"
    
    // Make sure that we include headers specifying that our request's HTTP body; this is done by helper function
    req = JsonHelper.defineCommonHeaders(request: req)
    print (req)
    
    JsonHelper.configSessionAndSendPalletNr(request: req) {
        returned in
        completionHandler(returned)
        print ("returned JSON INSIDE", palletCheckerResponse)
    }
    //        Remove  this line -> return palletCheckerResponse
}

This is because, by the time you receive your response in your configSessionAndSendPalletNr , the function returns the control.

Adding a closure will help.

To know more read about following topics

Closures in swift

@escaping vs @non-escaping

Async calls in swift.


推荐阅读