Completion with JSON

(Swift, macOS, Storyboards)

I can read a JSON from an URL. I would like to know when I can access the information. To be able to go from one function after the other. It seems that "completion" does not work with JSON? or perhaps I am doing something wrong?

I give a simplified example: I try to get the JSON information in func first() and then do something with that information in func second()

    var result2 = "empty"
    func first(completion: ()->()) {
        let url = URL(string: "https://jsonplaceholder.typicode.com/users")!
        URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data {
                let result = try? JSONDecoder().decode([User].self, from: data)
                self.result2 = result![0].name
            }
        }.resume()
        completion()
    }

    func second() {
        //do something after first()
        print (result2)
    }

    @IBAction func button1(_ sender: NSButton) {
        first {
          second()
        }
    }

Accepted Reply

You are putting completion() at the wrong place:

    func first(completion: @escaping ()->()) { //<-
        let url = URL(string: "https://jsonplaceholder.typicode.com/users")!
        URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data {
                let result = try? JSONDecoder().decode([User].self, from: data)
                self.result2 = result![0].name
                completion() //<- here
            }
        }.resume()
        //completion() //<- Not here
    }
  • It gives me an error I do not understand: Escaping closure capture non-escaping parameter 'completion'

  • Have noticed I have added @escaping on the first line?

  • It works perfectly. Thank you!

Add a Comment

Replies

Does the code compile ?

you call first() without completion label.

and you should pass the func, not its result.

try

first(completion: second  )
  • Like with my code I can run but I only get result 2 when I click a second time to the button. I suppose that it means that the functions do not go one after the other.

Add a Comment

You are putting completion() at the wrong place:

    func first(completion: @escaping ()->()) { //<-
        let url = URL(string: "https://jsonplaceholder.typicode.com/users")!
        URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data {
                let result = try? JSONDecoder().decode([User].self, from: data)
                self.result2 = result![0].name
                completion() //<- here
            }
        }.resume()
        //completion() //<- Not here
    }
  • It gives me an error I do not understand: Escaping closure capture non-escaping parameter 'completion'

  • Have noticed I have added @escaping on the first line?

  • It works perfectly. Thank you!

Add a Comment