Skip to content

Commit

Permalink
Support multithreaded downloads for RemoteData
Browse files Browse the repository at this point in the history
All posters for a search selection are downloaded before the first one
is shown in the UI.  For popular tv series, there can be 20 or more posters
for the series which are all downloaded before the 'first' poster appears in the UI.
Currently, the posters are downloaded serially which means that on a slow-ish
connection to tvDB (for eg) this can take quite a while before the 'first' poster
appears in the UI.

This patch moves patch downloading onto the global 'utility' thread which allows
for multiple simultaneous downloads, limiting the number of simultaneous
downloads to 10.
  • Loading branch information
dagronf committed Apr 26, 2022
1 parent ec5d74d commit d6a4254
Showing 1 changed file with 24 additions and 19 deletions.
43 changes: 24 additions & 19 deletions Framework/src/RemoteData.swift
Expand Up @@ -7,28 +7,27 @@

import Foundation

fileprivate class RemoteCaching {
// Used a session that caches its results
static let remoteLoadSession: URLSession = {
// Create URL Session Configuration
let configuration = URLSessionConfiguration.default.copy() as! URLSessionConfiguration
// Limit the number of simultaneous downloads
private let RemoteDownloadLimiter = DispatchSemaphore(value: 10)

// Set the in-memory cache to 128 MB
let cache = URLCache()
cache.memoryCapacity = 128 * 1024 * 1024
configuration.urlCache = cache
// A URLSession that caches its results
private let RemoteLoadSession: URLSession = {
// Create URL Session Configuration
let configuration = URLSessionConfiguration.default.copy() as! URLSessionConfiguration

// Define Request Cache Policy
configuration.requestCachePolicy = .useProtocolCachePolicy
configuration.urlCache = cache
// Set the in-memory cache to 128 MB
let cache = URLCache()
cache.memoryCapacity = 128 * 1024 * 1024
configuration.urlCache = cache

return URLSession(configuration: configuration)
}()
}
// Define Request Cache Policy
configuration.requestCachePolicy = .useProtocolCachePolicy
configuration.urlCache = cache

return URLSession(configuration: configuration)
}()

@objc public class RemoteData : NSObject {
private static let queue = DispatchQueue(label: "io.metaz.RemoteDataQueue")

public let url : URL
public let expectedMimeType : String

Expand Down Expand Up @@ -110,13 +109,19 @@ fileprivate class RemoteCaching {

let url = self.data!.url
let expectedMimeType = self.data!.expectedMimeType
RemoteData.queue.async {

DispatchQueue.global(qos: .utility).async {
RemoteDownloadLimiter.wait()
defer {
RemoteDownloadLimiter.signal()
}

var downloadData : Data?, responseError : NSError?
let signal = DispatchSemaphore(value: 0)
if self.data == nil {
return;
}
RemoteCaching.remoteLoadSession.dataTask(with: url) { (d, resp, err) in
RemoteLoadSession.dataTask(with: url) { (d, resp, err) in
if let error = err {
let info = [NSLocalizedDescriptionKey: error.localizedDescription]
let statusCode = (resp as? HTTPURLResponse)?.statusCode ?? 0
Expand Down

0 comments on commit d6a4254

Please sign in to comment.