0

I want to wait for a responseString to complete before calling the next function "nextScreen()" (segue). At the moment I have an if statement to make sure it is not nil before proceeding, but sometimes the the next function/segue is called because the responseString is still downloading.

Could you help with a completion block? I have found completion blocks for NSURLSession, but these just wait for the initial HTTP call to complete, not the response string.

func getProfiles(){
    func post(completion: (message: String?) -> Void) {
        let request = NSMutableURLRequest(URL: NSURL(string: "http://**.**.**.**/EPG/XML/QueryProfile")!)
        request.HTTPMethod = "POST"
        let postString = "<QueryProfileReq><type>1</type></QueryProfileReq>"
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

        let task: Void = NSURLSession.sharedSession().dataTaskWithRequest(request,
            completionHandler: {(data: NSData!,
                response: NSURLResponse!,
                error: NSError!) in
                if error != nil {
                    println("error=\(error)")
                    let alert = UIAlertView()
                    alert.delegate = self
                    alert.title = "Login Error"
                    alert.message = "\(error)"
                    alert.addButtonWithTitle("OK")
                    alert.show()
                    self.view.endEditing(true)
                    return
                }
                if let responseString = NSString(data: data, encoding: NSUTF8StringEncoding) {
                    if response != nil {
                        println("got profiles")
                        self.nextScreen()
                    }
                    self.dataVar = data // UPDATES VARIABLE TO SEND
                }
        }).resume()

    }
}
ThundercatChris
  • 451
  • 6
  • 24
  • possible duplicate of [How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest](http://stackoverflow.com/questions/31264172/how-can-i-get-the-data-from-nsurlsession-sharedsession-datataskwithrequest) – Eric Aya Jul 15 '15 at 16:26

1 Answers1

0

The convenience method of dataTaskWithRequest essentially returns data or error, with usually some response header type information. If you have an error then you won't have data (99% sure about this). I have re formatted your method to help. The NSString Init Convenience method is synchronous so not quite sure by what you mean by waiting to complete instead of http call?

func getStringFromRequest(completionHandler:(success:Bool, data: NSData?) -> Void) {

    let request = NSMutableURLRequest(URL: NSURL(string: "http://##.##.##.##/EPG/XML/QueryProfile")!)
    request.HTTPMethod = "POST"
    let postString = "<QueryProfileReq><type>1</type></QueryProfileReq>"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in

        if let unwrappedError = error {
            print("error=\(unwrappedError)")
        }
        else {
            if let unwrappedData = data {
                completionHandler(success: true, data: unwrappedData)
                return
            }
        }

        completionHandler(success: false, data: nil)
    }

    task?.resume()
}

func performPost() {

    getStringFromRequest { (success, data) -> Void in

        if (success) {

            if let unwrappedData = data {

                self.dataVar = unwrappedData

                if let responseString = NSString(data: unwrappedData, encoding: NSUTF8StringEncoding) {
                    self.nextScreen()
                }
            }
        }
        else {
            print("Failed")
        }
    }
}
Dave Roberts
  • 674
  • 3
  • 9
  • I need to get the full response string. then I am copying the data to an NSData variable. once that is done, I need to segue to a screen and copy the data across. It all needs to be in that order. Most of the time it works. But I need to ensure its done in this order. 1. response string fully received 2. data copied to variable 3. segue to new screen – ThundercatChris Jul 15 '15 at 16:51
  • Hi, i have edited answer to suggest how to handle this – Dave Roberts Jul 15 '15 at 17:28
  • Thanks for that. Although it doesn't bring any errors up. The app just hangs on this part now. Ive put some println's in to see whats running and what isn't. Its getting to if let unwrappedData = data { completionHandler(success: true, data: unwrappedData) and printing after. But its not going any further. Im also not sure where performPost is being called now? Though I am probably missing something obvious – ThundercatChris Jul 16 '15 at 09:20
  • You just need to call performPost(). The data fetch will be successful or not, then you can decide what to do if successful. I only meant this to demonstrate 1 way you could split up you code into functional chunks for clarity and show how a completionHandler can work. – Dave Roberts Jul 16 '15 at 09:33
  • Thats great thank you. I think my code was working (although not as well as yours), but that one in 5 times the server must drop out. Im just going to have to build something in for that. Thanks for your help! – ThundercatChris Jul 16 '15 at 09:40
  • Im finding that this code still has the same issue 1 in 7 times. It seems the if let unwrappedData = data { completionHandler(success: true, data: unwrappedData) println("got data") return } is the issue. This is not being called until everything completes in some cases. I don't think the 'Success' part is working properly? – ThundercatChris Jul 17 '15 at 08:42
  • In the example given, there are many parts where you should be checking for errors still. I.e if data can't be written to a string then the current example falls through without any output at all, this is bad. You need to account for all if/else cases to be able to narrow your problem down. – Dave Roberts Jul 17 '15 at 09:11