Continue with code after URLSession.shared.uploadTask is completed

2.4k Views Asked by At

I am trying to communicate with Swift to a php-website using the command "uploadTask". The site is sending Data back, which is working well. The result from the website is stored in the variable "answer". But how can I actually use "answer" AFTER the uploadTask.resume() was done?

When running the file, it always prints: "One" then "three" then "two".

I know that I could do things with "answer" right where the section "print("two")" is. And at many examples right there the command "DispatchQueue.main.async { ... }" is used. But I explicitly want to finish the uploadTask and then continue with some more calculations.

   func contactPHP() {

    print("One")

    let url = "http://....php" // website to contact
    let dataString = "password=12345" // starting POST
    let urlNS = NSURL(string: url)
    var request = URLRequest(url: urlNS! as URL)
    request.httpMethod = "POST"
    let dataD = dataString.data(using: .utf8) // convert to utf8 string

    URLSession.shared.uploadTask(with: request, from: dataD)
    {
        (data, response, error) in
        if error != nil {
            print(error.debugDescription)
        } else {
            let answer = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
            print("Two")
        }
        }.resume()  // Starting the dataTask

  print("Three")

 // Do anything here with "answer"

}

extension NSMutableData {
    func appendString(string: String) {
        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
        append(data!)
    }
}

I already tried it with a completion handler. But this does not work either. This also gives me "One", "Four", "Two", "Three"

func test(request: URLRequest, dataD: Data?, completion: @escaping (NSString) -> ()) {
    URLSession.shared.uploadTask(with: request, from: dataD)
    {
        (data, response, error) in
        if error != nil {
            print(error.debugDescription)
        } else {
            let answer = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
            print("Two")
            completion(answer)
        }
        }.resume()  // Starting the dataTask
    }

let blubb = test(request: request, dataD: dataD) { (data) in
    print("Three")
}

print("Four")
1

There are 1 best solutions below

0
Nathan On

Use the URLSession function that has the completion handler:

URLSession.shared.uploadTask(with: URLRequest, from: Data?, completionHandler: (Data?, URLResponse?, Error?) -> Void)

Replace your uploadTask function with something like this:

URLSession.shared.uploadTask(with: request, from: dataD) { (data, response, error) in

     if let error = error {
          // Error
     }

     // Do something after the upload task is complete

}

Apple Documentation

After you create the task, you must start it by calling its resume() method. If the request completes successfully, the data parameter of the completion handler block contains the resource data, and the error parameter is nil.

If the request fails, the data parameter is nil and the error parameter contain information about the failure. If a response from the server is received, regardless of whether the request completes successfully or fails, the response parameter contains that information.

When the upload task is complete, the completion handler of the function is called. You could also implement the delegate's optional func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) function.