0

I'm trying to make a application that uses a online rest API. It's retrieving the data via a URLSession. In the do{} method, the entire array is filled correctly. However, when I'm returning the array, all of a sudden it is completely empty. Can someone explain to me what I'm doing wrong?

// Makes a request to the API
func makeRequest(url: URL) -> Array<Any>{
    var allItems = [[ApiItem]]()

    // Make request
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }

        // Do the request
        do{
            // Get the JSON
            let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: AnyObject]

            // Get the right entry
            let results = json["items"] as? [AnyObject]

            // Loop through the results
            for r in results! {
                // Create a item
                let item = ApiItem(json: r as! [String : Any])

                // Add them to the array
                allItems.append([item])

                print("Items in array after appending: \(allItems.count)") // The entire array gets correctly filled here
            }

        } catch let jsonErr{
            print("JSON ERROR! \(jsonErr)")
        }
    }.resume()

    return allItems // The array is empty right here
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
kaanmijo
  • 713
  • 1
  • 5
  • 14
  • 3
    Because it's async, and if you do a `print()` just before `return allItems` you'll see it's printed before `print("Items in array after appending: \(allItems.count)"` . Use a closure. – Larme Sep 01 '17 at 14:16
  • Follow the linked example. Just replace "String" in the example handler with your own type for allItems, ie "[[ApiItem]]", but this is exactly the same idea. // I've added this dupe link because I know it, it's mine - but there's many others. Search on "callback", "closure", "asynchronous" and "completion handler". – Eric Aya Sep 01 '17 at 14:18
  • @Moritz Thanks! I've managed to get it working. The next problem is, however, that I have to return that data from the closure. Can you explain me how to do that? [Screenshot of my code](http://imgur.com/a/09kKM). I have tried to append that allData array with the data, but that does not work. – kaanmijo Sep 01 '17 at 15:20
  • Well, you don't return from a closure, that's the whole point of using a callback, as explained in the link. So I would be ok to show an example, but... there's already one. I'm not sure how I could help more. :) // Read the comments in my example code, I explain where and how you "return" in this case. – Eric Aya Sep 01 '17 at 15:22
  • I just saw your screenshot. The code in there is different from the one in your question... // Here's another example I posted today, it should inspire you: https://stackoverflow.com/a/45999847/2227743 – Eric Aya Sep 01 '17 at 15:25
  • I don't think your "doRequest" returns a value that you can store in a variable. Instead,just use "doRequest" and inside its closure call the completion. – Eric Aya Sep 01 '17 at 15:26
  • Please try all this. If you still don't understand, I would suggest you post a new question with the same code as in your screenshot. But really I'm sure you can do it. Try again. ;) – Eric Aya Sep 01 '17 at 15:27

0 Answers0