0

I have the following method called under ViewDidLoad(). I understand that session.dataTaskWithRequest automatically runs in background thread. And because of the same, the code following this method in ViewDidLoad() does not wait for this process to complete and starts executing.

Is there any way that I can ensure that the background thread is completed before other methods are executed?

    func getCoordinatesFromServer() {
        let request = NSMutableURLRequest(URL: NSURL(string: constants.urlName.loadData)!)
        request.HTTPMethod = "POST"
        request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
        request.setValue("keep-Alive", forHTTPHeaderField: "Connection")
        request.HTTPBody = (constants.requestTag.getCoordinates).data

        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithRequest(request, completionHandler: {(data, response ,error ) in
            if let response = response {
                let httpResponse = response as! NSHTTPURLResponse

                print("response code = \(httpResponse.statusCode)")
                if (httpResponse.statusCode == 200) {
                    dispatch_async(dispatch_get_main_queue(), {
                        let decodedData = NSData(base64EncodedData: data!, options: NSDataBase64DecodingOptions([]))
                        let jsonText = NSString(data: decodedData!, encoding: NSASCIIStringEncoding) as! String
                        do {
                        let json = try NSJSONSerialization.JSONObjectWithData(jsonText.data, options: NSJSONReadingOptions.init(rawValue: 0))
                        self.parseJsonData(json["Datalist"] as! NSArray)
                        } catch {
                        print("Error:\n \(error)")
                        }
                    })
                }
            }
        })
        task.resume()
    }

Regards,

PK20
  • 1,066
  • 8
  • 19

3 Answers3

1

if I understand your question, you can solve this problem at this way For example:

class func ConnectedToNetwork(completionHandler: ((Status: Bool) -> Void))
    {
    let url = NSURL(string: "http://google.com")
    let request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod =  "HEAD"
    request.timeoutInterval = 0.2
       let task = NSURLSession.sharedSession().dataTaskWithURL(url!)    {(data,response, error) in
            let httpResponse = response as! NSHTTPURLResponse
                if httpResponse.statusCode == 200
                {   completionHandler(Status: true)
                    return
                }
        }
        task.resume()
    }

and then, you can work with this

Checks.ConnectedToNetwork({ Status in dispatch_async(dispatch_get_main_queue())
        {
            if Status == true
            {
                //do what you want
             }
});
0

dataTaskWithRequest is assync call, and it has completionHandler block. So all code that you wrote inside will be executed after the data task finished:

let request = NSURLRequest(URL: NSURL(string: "http://google.com")!)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {(data, response ,error ) in
    print("3") // executed after data task is finished
    print("4") // executed after data task is finished
})
task.resume()
print("1")
print("2")
katleta3000
  • 2,484
  • 1
  • 18
  • 23
  • Thanks for your time in answering it. I understand that the completion handler gets called after the data task is finished. My question is `if I have to use this dataTaskWithRequest` in ViewDidLoad() method how should I ensure the completion handler is executed before executing other methods. – PK20 Oct 30 '15 at 08:24
  • move those methods to your `viewDidLoad` section – katleta3000 Oct 30 '15 at 08:59
  • It doesn't seem to be a good solution. I am not sure if you understood my question or not. – PK20 Oct 30 '15 at 09:22
-1
import Foundation

// some aync function with completition handler, i MUST USE AS IT IS
func f(completitionHandler: ()->()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { () -> Void in
        print("running concurrently")
        sleep(1)
        print("finished")
        completitionHandler()
    }
}

// some function running on main queue
func foo() {
    // create dispatch group
    let group = dispatch_group_create()
    let myCompletitionHandler: ()->() = {
        dispatch_group_leave(group)
    }
    let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
    dispatch_group_async(group, queue) { () -> Void in
        dispatch_group_enter(group)
        f(myCompletitionHandler)
    }
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
}

foo()
print("foo finished")

It is not the best at all, the better solution is to run synchronous version of f() instead of this 'workaround':-)

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • PK20 asks: "how should I ensure the completion handler is executed before executing other methods". I don't understand, why somebody complain with my answer ... I don't say, that this "wokraround" is the best programmers practice. I just try to explain, how to wait for further program execution until all async code finished. what is wrong with my answer? by the way, this technic could be very useful sometimes ... – user3441734 Nov 01 '15 at 12:31