12

I am using URLSession in my iOS project. (Swift 4). The following code is only for illustration purpose.

class MyTaskManager {
    ...
    func postMyData(...) {
       let defaultSession = URLSession(configuration: .default)
       dataTask = defaultSession.dataTask(with: url) { data, response, error in
         ...
       }
       dataTask.resume()
    }


    func getMyData(...) {
       let defaultSession = URLSession(configuration: .default)
       dataTask = defaultSession.dataTask(with: url) { data, response, error in
         ...
       }
       dataTask.resume()
    }

}

I am trying to understand the best practice of using URLSession in the sense of whether each function call of making HTTP request should create a new URLSession or should I create a global one & all the calls to HTTP requests should use the same URLSession instance?

I have studied on internet, there is an accepted answer which says I should create a new URLSession for each function/request call , there is/are also suggestions that I should reuse the same URLSession. I get confused by those accepted but conflicting answers. Could someone clarify for me the correct answer to this question?

My application doesn't have upload or download tasks, only pure RESTful request with JSON data format. No multiple configurations needed either.

Leem
  • 17,220
  • 36
  • 109
  • 159
  • 1
    You must use a single URLSession throughout. Otherwise, it can't manage your simultaneous connections for you (plus there is a lot of other unnecessary overhead). Please watch the WWDC 2018 video on this topic if you want to hear this from Apple's own mouth. – matt Oct 01 '18 at 13:54
  • Thanks @matt for pointing that out. Here's the direct link to what you mentioned: https://developer.apple.com/videos/play/wwdc2018/714/?time=1646 – heyfrank Jan 28 '21 at 09:51

3 Answers3

8

You should create a shared instance of the data session and use the same creating multiple tasks because it's rarely the case that you need to have a different configuration for an api.

I suggest and use the shared instance of data session for getting data from an api.

class MyTaskManager {

    static let sessionManager: URLSession = {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30 // seconds
        configuration.timeoutIntervalForResource = 30 // seconds
        return URLSession(configuration: configuration)
    }()

    func postMyData(...) {
        dataTask = sessionManager.dataTask(with: url) { data, response, error in
            ...
        }
        dataTask.resume()
    }


    func getMyData(...) {
        dataTask = sessionManager.dataTask(with: url) { data, response, error in
            ...
        }
        dataTask.resume()
    }
}

The benefit of this is that I had to create the session only once, so that will save repetition of same code and also the process to initialise the same thing again per api request. This will be more helpful in case you need to more custom configuration of the session.

Nike Kov
  • 12,630
  • 8
  • 75
  • 122
Aakash
  • 2,239
  • 15
  • 23
  • Could you please be more detailed because when you say "shared instance of data session", it sounds to me like two things 1 `URLSession.shared` 2. Globally shared URLSession instance in app created with defaultConfiguration like my code snippet shows. Which one do you mean exactly? – Leem Oct 01 '18 at 13:13
  • It also would be nice to explain the drawbacks of not using shared instance in my case. Thanks. – Leem Oct 01 '18 at 13:14
  • I have added more info to the answer pls let me know if this helps – Aakash Oct 01 '18 at 13:21
  • With your code snippet, is it possible to inject mocked session in unit test of `MyTaskManager`? – Leem Oct 01 '18 at 13:36
  • Sorry I haven't worked on xc tests, so someone else might be able to help with the unit test issue – Aakash Oct 01 '18 at 13:41
  • Thanks, you already answered my question, I will wait a while to see if any other opinions with reasons. – Leem Oct 01 '18 at 13:43
  • Again, 2018 wwdc video on testing explains how to mock URLSession. – matt Oct 01 '18 at 14:15
3

Most of the time, you should use a single session for all of your work. This allows the session to limit simultaneous requests to a single host (limiting the potential for accidental abuse), and also is significantly more memory efficient than using a new session for each request.

If you have multiple groups of tasks that need to be canceled as a group (for example, uploading all of the images in a new album, downloading all the resources for loading a single web page, etc.), or multiple requests that need a different configuration (e.g. background downloads) then it makes sense to use one session per group or configuration.

Alternatively, if you don't need to make any configuration changes to the default and are happy with just running a block when each request finishes, you can also use the shared session ([NSURLSession sharedSession]) rather than creating a session at all.

dgatwood
  • 10,129
  • 1
  • 28
  • 49
1

-It depends on your usage of the URLSession Object. -You will create a new one if you need to create your configuration & assign a delegate. -You will use the shared instance if you won't change neither the configuration nor setting a delegate.

Also this part from the Apple documentation regarding the shared instance limitation:

the shared session has important limitations: -You can’t obtain data incrementally as it arrives from the server. -You can’t significantly customize the default connection behavior. -Your ability to perform authentication is limited. -You can’t perform background downloads or uploads when your app isn’t running.