0

I have a callback function that returns an NSDictionary:

override func viewDidLoad()
{
    super.viewDidLoad()


    var nd: NSDictionary = [:]
    parseJSON(callback: {dict in
        nd = dict
        //print(nd)     This one prints the filled dictionary correctly
    })
    //print(nd)     This one prints an empty dictionary

}

I want to store the values returned from the callback function in "nd", but the print statement outside the callback is still printing an empty NSDictionary.

What am I doing wrong here, and how can I fix it?

EDIT:

var nd: NSDictionary! = nil

    override func viewDidLoad()
    {
        super.viewDidLoad()
        loadData()
        print(self.nd)
    }

    func loadData()
    {
        parseJSON(callback: {dict in
            self.nd = dict
            print(self.nd)
        })
    }

I changed it to this, so the function completes its loading, and then prints. However, the print statement in viewDidLoad() prints before the one in loadData(), and the print statement in viewDidLoad() still prints nil. Why does this happen, and what do I need to change specifically?

  • See my answer to this thread: http://stackoverflow.com/questions/41209804/waiting-for-asynchronous-function-call-to-complete/41209941#41209941. – Duncan C Apr 14 '17 at 02:17
  • parseJSON() is an async function. It returns immediately, before the work you've asked it to do is complete. Once the work IS finished, it invokes the callback you pass to it. You need to put the code that will get the data inside the braces of the callback function. – Duncan C Apr 14 '17 at 02:18
  • @DuncanC Thanks for the info. See my edit, can you explain? – Rushil Joshi Apr 14 '17 at 03:06
  • Because your `parseJSON()` function returns before the work is done, `loadData()` also returns before the work is done. Simply call `parseData()` directly and pass in a completion handler that will get run when the results are available. If you want another intermediate function, `loadData()`, then you need to make it take a completion handler. Go look at my answer in the duplicate question. It illustrates what to do. – Duncan C Apr 14 '17 at 11:14

1 Answers1

0

Looks like the parseJSON runs in the background and might only complete after your viewDidLoad method ends. As such, nd will stay empty immediately after the call.

My suggestion: add your dictionary processing logic inside the aforementioned callback (and then copy the results to a variable outside your viewDidLoadmethod).

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
  • so should I initialize "nd" outside of the viewDidLoad method, and then access it outside in another method? How can I fix it? – Rushil Joshi Apr 14 '17 at 00:49
  • You could do that, but the exact timing might be tricky to get right. Your best bet is to add your logic *inside* the actual callback. – Paulo Mattos Apr 14 '17 at 00:52
  • Thank you. I can probably make my logic work inside the callback, but is it possible to get the data outside of the callback function at all (just out of curiosity)? – Rushil Joshi Apr 14 '17 at 01:01
  • @RushilJoshi Yes, sure! You can assign the `dict` to a `var nd: NSDictionary!` outside the function. But you will need to **wait** for the callback to set it before your read it elsewhere (otherwise you would get a nil value). That's the tricky part I mentioned earlier... ;-) – Paulo Mattos Apr 14 '17 at 01:05