0
votes

I tried to send a request to get a JSON from Amazon by Alamofire, but it asynchronized. it comes back to the caller function before getting the response from Amazon.

public func getJSON(fileName: String) -> JSON?{
    let url = "http://s3.eu-west-3.amazonaws.com" + fileName
    print(self.json)

    if self.json == nil {
        Alamofire.request(url)
            .responseJSON { response in
                if let result = response.result.value {
                    self.json = JSON(result)
                }

        }
       return self.json
    }
    else{
        return nil
    }
}

public func initTableView(){
    let myJson = AmazonFiles.shared.getJSON(fileName: "/jsonsBucket/myJson.json")
    print(myJson["id"])
}

the object myJson in initTableView function is always nil.

How could I resolve this issue?

2

2 Answers

1
votes

Instead of returning JSON? in the method signature, use a completion closure like this:

public func getJSON(fileName: String, completion: ((JSON?) -> Void)?) {
    let url = "http://s3.eu-west-3.amazonaws.com" + fileName
    Alamofire.request(url).responseJSON { response in
        if let result = response.result.value {
            completion?(JSON(result))
        } else {
            completion?(nil)
        }
    }
}

And call the method like this:

getJSON(fileName: "/jsonsBucket/myJson.json") { json in
    print(json)
}

Or:

getJSON(fileName: "/jsonsBucket/myJson.json", completion: { json in
    print(json)
})
0
votes

You need to implement a completion handler, have a look on this article.

The completion handler is the code that we get to provide to get called when it comes back with those items. It's where we can work with the results of the call: error checking, saving the data locally, updating the UI, whatever.

typealias completionHandler = (JSON?) -> Void // this is your completion handler

public func getJSON(fileName: String, completionHandler: @escaping completionHandler) -> JSON?{
    let url = "http://s3.eu-west-3.amazonaws.com" + fileName
    if self.json == nil {
        Alamofire.request(url)
            .responseJSON { response in
                if let result = response.result.value {
                  completionHandler(json) // this will fire up your completion handler,
                }
        }
    }
    else{
        completionHandler(nil)
    }
}

And you can use it like this.

getJSON(fileName: "fileName") { (json) in
    // this will fire up when completionhandler clousre in the function get triggered
    //then you can use the result you passed whether its JSON or nil
    guard let result = json  else { return } // unwrap your result and use it
    print(result)
}