randall
randall

Reputation: 173

how i can make a HTTP request with Swift 3?

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

Upvotes: 1

Views: 4122

Answers (3)

OOPer
OOPer

Reputation: 47876

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)
    }

Upvotes: 2

Jason Rahaim
Jason Rahaim

Reputation: 11

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)")
}

Upvotes: 1

Jim Matthews
Jim Matthews

Reputation: 1191

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.

Upvotes: 0

Related Questions