12 Replies
      Latest reply on May 15, 2018 7:18 PM by ronak2121
      adarr Level 1 Level 1 (0 points)

        In a production app, I am setting the httpMaximumConnectionsPerHost property to 1 on a URLSessionConfiguration object when creating a URLSession.  This allows me to queue a number of downloads, but only download 1 file at a time.  Recently I noticed that all queued files download simultaneously on iOS 10 devices.

         

        Has anyone else noticed this change?  Is this intentional or a bug?

         

        Note: I am setting the value of httpMaximumConnectionsPerHost both before and after creating the session, because of a post I found months ago that suggested that some properties of URLSessionConfiguration must be set after creating a URLSession in order for them to take effect.

         

            let configuration = URLSessionConfiguration.background(withIdentifier: sessionIdentifier)
            configuration.httpMaximumConnectionsPerHost = 1
           
            session = URLSession(
              configuration: configuration,
              delegate: self,
              delegateQueue: nil
            )
           
            session.configuration.httpMaximumConnectionsPerHost = 1
        
        • Re: URLSessionConfiguration's httpMaximumConnectionsPerHost not working in iOS 10?
          eskimo Apple Staff Apple Staff (9,180 points)

          You’re doing this in a background session.  What happens if you do it in a standard session?


          I am setting the value of httpMaximumConnectionsPerHost both before and after creating the session, because of a post I found months ago that suggested that some properties of URLSessionConfiguration must be set after creating a URLSession in order for them to take effect.

          That’s not something I’m aware of.  The general model for session configurations is that, when you create a session from a configuration, the session should ‘latch’ a copy of the configuration and use that from then on.  This hasn’t been implemented perfectly in all releases of the OS, but there’s no circumstances where setting configuration properties after creating the session is a good idea.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: URLSessionConfiguration's httpMaximumConnectionsPerHost not working in iOS 10?
              adarr Level 1 Level 1 (0 points)

              A session created with URLSessionConfiguration.default has the same behavior.  A background session is a requirement in this situation, as the files I'm downloading could be large & may have to be downloaded if the app isn't active.

                • Re: URLSessionConfiguration's httpMaximumConnectionsPerHost not working in iOS 10?
                  eskimo Apple Staff Apple Staff (9,180 points)

                  A background session is a requirement in this situation …

                  Understood.  I was just asking because it’s an interesting diagnostic test.

                  A session created with URLSessionConfiguration.default has the same behavior.

                  OK.

                  I just tried both of these situations on a device here in my office and httpMaximumConnectionsPerHost is working as I’d expect.  Specifically:

                  1. I started two downloads, A and B

                  2. A immediately begins to make progress and B does not

                  3. If I cancel A, B starts to make progress

                  Are you sure all of these downloads are targeting the same host?

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: URLSessionConfiguration's httpMaximumConnectionsPerHost not working in iOS 10?
                      adarr Level 1 Level 1 (0 points)

                      I created a new project today from the "Single View Application" template.  I replaced ViewController.swift with the following:

                       

                      import UIKit
                      class ViewController: UIViewController {
                        override func viewDidLoad() {
                          super.viewDidLoad()
                          let url = URL(string: "REDACTED")!
                          let request1 = URLRequest(url: url)
                          let request2 = URLRequest(url: url)
                          session.downloadTask(with: request1).resume()
                          session.downloadTask(with: request2).resume()
                        }
                      }
                      var session: URLSession = {
                        let configuration = URLSessionConfiguration.background(withIdentifier: "DownloadTest")
                        configuration.httpMaximumConnectionsPerHost = 1
                        
                        return URLSession(
                          configuration: configuration,
                          delegate: SessionWorker(),
                          delegateQueue: nil
                        )
                      }()
                      class SessionWorker: NSObject, URLSessionDownloadDelegate {
                        func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
                          print(downloadTask.taskIdentifier)
                        }
                        
                        func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
                        }
                        
                        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
                          if let error = error {
                            print(error)
                          }
                          
                          if let response = task.response as? HTTPURLResponse {
                            print(response.statusCode)
                          }
                        }
                      }
                      

                       

                      On iOS 9 (9.3.5, iPad Air 2 in my most recent test) devices, the didWriteData delegate method is called repeatedly for the first downloadTask, followed by a call to didCompleteWithError for the first downloadTask.  Then, similar calls are made for the second downloadTask.  On iOS 10 (10.2.1, iPhone 7 Plus in my most recent test), I receive calls many calls to didWriteData for both the first and second downloadTasks before a call to didCompleteWithError is made.

                       

                      I have tested files from my company's servers, third party servers, and even the same URL for both downloadTasks.  I have also tested on WIFI and LTE.  All devices that download one file at a time are running some version of iOS 9.  All devices that download many files at a time are running some version of iOS 10.

                       

                      Was your test similar?  Am I missing something?

                • Re: URLSessionConfiguration's httpMaximumConnectionsPerHost not working in iOS 10?
                  diogomusou Level 1 Level 1 (0 points)

                  I found out that, for background sessions, setting "timeoutIntervalForRequest" to a very high value actually makes the next task on queue to wait until the previous task is over (or until the value set at timeoutIntervalForRequest is over). This looks like a bug, but it worked for me.

                  If you don’t set anything, I think the default is 60 seconds, so the next task will start after 60 seconds, regardless of httpMaximumConnectionsPerHost being 1.