1

Im learning about Swift and i trying to make an HTTP request. My code is working but i dont know how to return the result of the request:

func makeRequest(request: URLRequest)->String{
    let task = URLSession.shared.dataTask(with: request){data, response, error in
        guard let data = data, error == nil else{
            print("error=\(error)")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }
        print (data)
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(json)
        } catch {
            print("error serializing JSON: \(error)")
        }
        //print("responseString = \(responseString)")

    }
    task.resume()
    return "Something"//i need to return the json as String
}

Someone can help me please? i was trying using CompletionHanlder but all the example that i found is based on swift 2, and this causes error on my code

enter image description here

randall
  • 163
  • 3
  • 14
  • 1
    [How do you write a completion handler in Swift 3?](http://stackoverflow.com/questions/39643334/how-do-you-write-a-completion-handler-in-swift-3) is the first hit for `[swift3] completion handler`... – Martin R Oct 20 '16 at 20:42

3 Answers3

2

The completion handler's type needs to be something like this:

@escaping ({argument types...})->{result type}

@escaping is needed as the completion handler is executed later when the communication is completed.

{argument types...} needs to be the types you want to pass to the handler, so in your case, a single type String. And you usually do not use the result from the handler, so you need to specify Void (aka ()).

Thus your completion handler's type needs to be:

@escaping (String)->Void

So, your method header becomes:

(You know you need a closing parenthesis for argument list.)

func makeRequest(request: URLRequest, completion: @escaping (String)->Void)

Whole your method would be something like this:

func makeRequest(request: URLRequest, completion: @escaping (String)->Void) {
    let task = URLSession.shared.dataTask(with: request) {data, response, error in
        guard let data = data, error == nil else{
            print("error=\(error)")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }
        print(data as NSData) //<-`as NSData` is useful for debugging
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(json)
            //Why don't you use decoded JSON object? (`json` may not be a `String`)
        } catch {
            print("error serializing JSON: \(error)")
        }
        //Not sure what you mean with "i need to return the json as String"
        let responseString = String(data: data, encoding: .utf8) ?? ""
        completion(responseString)
    }
    task.resume()
}

You can use it as:

    makeRequest(request: request) {response in //<-`response` is inferred as `String`, with the code above.
        print(response)
    }
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • Thank you so much @OOPer, the code works perfectly and i understand your explication. You are right, and i will use JSON jeje, Thanks you again – randall Oct 25 '16 at 19:37
1
func makeRequest(request: URLRequest, completion: (result : String?)->() {
    let task = URLSession.shared.dataTask(with: request){data, response, error in
    guard let data = data, error == nil else{
        print("error=\(error)")
        return
    }

    if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
        print("statusCode should be 200, but is \(httpStatus.statusCode)")
        print("response = \(response)")
    }
    print (data)
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(json)
        } catch {
            print("error serializing JSON: \(error)")
        }
        completion("yourResultString")
    //print("responseString = \(responseString)")

    }
    task.resume()
}

to call it

makeRequest(request: request) { (result : String?) in 
    if let result = result {
        print("got result: \(result)")
}
  • Thank you for your help friend, i tried with this way but i obtain different error and maybe for a ")" , i solved one of them but not all. [link](https://i.stack.imgur.com/o0coP.png) – randall Oct 23 '16 at 22:16
0

You can't "return" the result of the request. By the time you have a result your makeRequest function has already returned to its caller. You should:

  1. Change makeRequest to not return anything, because there's no point
  2. Replace the commented-out print statement with code that does something with the responseString result.
Jim Matthews
  • 1,181
  • 8
  • 16