3

I am using NSURLSession in my app like so:

func wsQAshowTag(tag: Int, completion: ([AnyObject]! -> Void)) {
        let requestString = NSString(format: “URL”, tag) as String
        let url: NSURL! = NSURL(string: requestString)
        let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {
            data, response, error in
            do {
                let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! [AnyObject]
                completion(result)
            }
            catch {
                completion(nil)
            }
        })
        task.resume()
    }

This works as expected, however I am finding it very very slow, when I was using NSURLConnection I found it extremely fast (this is with the same URL) How come NSURLSession is very slow when NSURLConnection is very fast? and is there away to speed up NSURLSession?

Here is how I am calling it:

self.wsQAshowTag(Int(barcode)!, completion: { wsQAshowTagArray in
     //Code Here
})
user979331
  • 11,039
  • 73
  • 223
  • 418
  • Do you know that this is a async method ? and run on background thread ? – Mudith Chathuranga Silva May 26 '16 at 03:45
  • You are using for `POST` or `GET` method? – Sohil R. Memon May 26 '16 at 04:13
  • 1
    `How come NSURLSession is very slow` It's not. A network request is a network request, its speed is independent of the method you're using to make it. But maybe, since it's an asynchronous method running in the background, you need to bring back the completion to the main thread? – Eric Aya May 26 '16 at 09:54

2 Answers2

7

You need to send UI updates to the main queue. If you update it without sending it to the main queue it can take a very long time to update data.

You also need to wrap completion(result) since we're parsing JSON.

The code grabs the stored completion handler and invokes it on the main thread.

func wsQAshowTag(tag: Int, completion: ([AnyObject]! -> Void)) {
let requestString = NSString(format: "URL", tag) as String
let url: NSURL! = NSURL(string: requestString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {
    data, response, error in
    do {
        let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! [AnyObject]
        dispatch_async(dispatch_get_main_queue()) {
            completion(result)
        }
    } catch {
        dispatch_async(dispatch_get_main_queue()) {
        completion(nil)
        }
        print("error serializing JSON: \(error)")
    }
})
task.resume()
}
Edison
  • 11,881
  • 5
  • 42
  • 50
  • I'll let the author decide and am removing my comment regarding what answer should be accepted. – Andrej Jul 16 '16 at 06:57
  • 1
    @Andrej you said my answer should be the accepted answer then you deleted your comment lol. There is nothing wrong with having an opinion. Don't let anyone bully you. – Edison Jul 16 '16 at 07:20
  • Sulthan. If you check my edit you will see I already wrapped both completions with dispatch_async. I have been editing my answer for the past 5 minutes. I don’t tell the author to read a tutorial. I give the author a thorough and completed answer with a code solution which the author benefits from. I also added more information about parsing data on the main thread as well as added console output for error in the catch. – Edison Jul 16 '16 at 07:24
  • 2
    In Swift 3 it should be: `DispatchQueue.main.async`. – zvi Mar 22 '17 at 10:54
0

You should add

dispatch_async(dispatch_get_main_queue()) {
    ...
}

around every completion(...) if the completion handler changes UI state (which it usually does).

The completion handler of URL Session is called on a background queue and changing UI from a background thread is wrong and usually creates long pauses.

This is different from NSURLConnection where the delegate methods were always called on the thread that has started the connection, that is, usually the main thread.

See for example in this tutorial.

Sulthan
  • 128,090
  • 22
  • 218
  • 270