title: Apple Combine framework: How to execute multiple Publishers in parallel and wait for all of them to finish?
body: <p>I am discovering Combine. I wrote methods that make HTTP requests in a "combine" way, for example:</p>
  
  <pre class="lang-swift prettyprint-override"><code>func testRawDataTaskPublisher(for url: URL) -&gt; AnyPublisher&lt;Data, Error&gt; {
      var request = URLRequest(url: url,
                               cachePolicy: .useProtocolCachePolicy,
                               timeoutInterval: 15)
      request.httpMethod = "GET"
  
      return urlSession.dataTaskPublisher(for: request)
          .tryMap {
              return $0.data
          }
          .eraseToAnyPublisher()
  }
  </code></pre>
  
  <p>I would like to call the method multiple times and do a task after all, for example:</p>
  
  <pre class="lang-swift prettyprint-override"><code>let myURLs: [URL] = ...
  
  for url in myURLs {
      let cancellable = testRawDataTaskPublisher(for: url)
          .sink(receiveCompletion: { _ in }) { data in
              // save the data...
          }
  }
  </code></pre>
  
  <p>The code above won't work because I have to store the cancellable in a variable that belongs to the class.
  The first question is: is it a good idea to store many (for example 1000) cancellables in something like <code>Set&lt;AnyCancellable&gt;</code>??? Won't it cause memory leaks?</p>
  
  <pre class="lang-swift prettyprint-override"><code>var cancellables = Set&lt;AnyCancellable&gt;()
  
  ...
  
      let cancellable = ...
  
      cancellables.insert(cancellable) // ???
  </code></pre>
  
  <p>And the second question is: how to start a task when all the cancellables are finished? I was thinking about something like that</p>
  
  <pre class="lang-swift prettyprint-override"><code>class Test {
      var cancellables = Set&lt;AnyCancellable&gt;()
  
      func run() {
          // show a loader
  
          let cancellable = runDownloads()
              .receive(on: RunLoop.main)
              .sink(receiveCompletion: { _ in }) { _ in
                  // hide the loader
              }
  
          cancellables.insert(cancellable)
      }
  
      func runDownloads() -&gt; AnyPublisher&lt;Bool, Error&gt; {
          let myURLs: [URL] = ...
  
          return Future&lt;Bool, Error&gt; { promise in
              let numberOfURLs = myURLS.count
              var numberOfFinishedTasks = 0
  
              for url in myURLs {
                  let cancellable = testRawDataTaskPublisher(for: url)
                      .sink(receiveCompletion: { _ in }) { data in
                          // save the data...
                          numberOfFinishedTasks += 1
  
                          if numberOfFinishedTasks &gt;= numberOfURLs {
                              promise(.success(true))
                          }
                      }
  
                  cancellables.insert(cancellable)
              }
          }.eraseToAnyPublisher()
      }
  
      func testRawDataTaskPublisher(for url: URL) -&gt; AnyPublisher&lt;Data, Error&gt; {
          ...
      }
  }
  </code></pre>
  
  <p>Normally I would use <code>DispatchGroup</code>, start multiple HTTP tasks and consume the notification when the tasks are finished, but I am wondering how to write that in a modern way using Combine.</p>