|
@@ -31,10 +31,6 @@ import AppKit
|
|
|
import UIKit
|
|
import UIKit
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-// The dispatch queue to use for handling resource process, so downloading does not occur on the main thread
|
|
|
|
|
-// This prevents stuttering when preloading images in a collection view or table view.
|
|
|
|
|
-private let prefetchQueue = DispatchQueue(label: "com.onevcat.Kingfisher.PrefetchQueue")
|
|
|
|
|
-
|
|
|
|
|
/// Progress update block of prefetcher.
|
|
/// Progress update block of prefetcher.
|
|
|
///
|
|
///
|
|
|
/// - `skippedResources`: An array of resources that are already cached before the prefetching starting.
|
|
/// - `skippedResources`: An array of resources that are already cached before the prefetching starting.
|
|
@@ -156,45 +152,38 @@ public class ImagePrefetcher {
|
|
|
/// Starts to download the resources and cache them. This can be useful for background downloading
|
|
/// Starts to download the resources and cache them. This can be useful for background downloading
|
|
|
/// of assets that are required for later use in an app. This code will not try and update any UI
|
|
/// of assets that are required for later use in an app. This code will not try and update any UI
|
|
|
/// with the results of the process.
|
|
/// with the results of the process.
|
|
|
- public func start()
|
|
|
|
|
- {
|
|
|
|
|
- // Since we want to handle the resources cancellation in the prefetch queue only.
|
|
|
|
|
- prefetchQueue.async {
|
|
|
|
|
-
|
|
|
|
|
- guard !self.stopped else {
|
|
|
|
|
- assertionFailure("You can not restart the same prefetcher. Try to create a new prefetcher.")
|
|
|
|
|
- self.handleComplete()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- guard self.maxConcurrentDownloads > 0 else {
|
|
|
|
|
- assertionFailure("There should be concurrent downloads value should be at least 1.")
|
|
|
|
|
- self.handleComplete()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ public func start() {
|
|
|
|
|
+ guard !stopped else {
|
|
|
|
|
+ assertionFailure("You can not restart the same prefetcher. Try to create a new prefetcher.")
|
|
|
|
|
+ handleComplete()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Empty case.
|
|
|
|
|
- guard self.prefetchResources.count > 0 else {
|
|
|
|
|
- self.handleComplete()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let initialConcurrentDownloads = min(self.prefetchResources.count, self.maxConcurrentDownloads)
|
|
|
|
|
- for _ in 0 ..< initialConcurrentDownloads {
|
|
|
|
|
- if let resource = self.pendingResources.popFirst() {
|
|
|
|
|
- self.startPrefetching(resource)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ guard maxConcurrentDownloads > 0 else {
|
|
|
|
|
+ assertionFailure("There should be concurrent downloads value should be at least 1.")
|
|
|
|
|
+ handleComplete()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Empty case.
|
|
|
|
|
+ guard prefetchResources.count > 0 else {
|
|
|
|
|
+ handleComplete()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let initialConcurrentDownloads = min(prefetchResources.count, maxConcurrentDownloads)
|
|
|
|
|
+ for _ in 0 ..< initialConcurrentDownloads {
|
|
|
|
|
+ if let resource = self.pendingResources.popFirst() {
|
|
|
|
|
+ self.startPrefetching(resource)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Stops current downloading progress, and cancel any future prefetching activity that might be occuring.
|
|
/// Stops current downloading progress, and cancel any future prefetching activity that might be occuring.
|
|
|
public func stop() {
|
|
public func stop() {
|
|
|
- prefetchQueue.async {
|
|
|
|
|
- if self.finished { return }
|
|
|
|
|
- self.stopped = true
|
|
|
|
|
- self.tasks.values.forEach { $0.cancel() }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if finished { return }
|
|
|
|
|
+ stopped = true
|
|
|
|
|
+ tasks.values.forEach { $0.cancel() }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func downloadAndCache(_ resource: Resource) {
|
|
func downloadAndCache(_ resource: Resource) {
|
|
@@ -270,13 +259,11 @@ public class ImagePrefetcher {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func reportCompletionOrStartNext() {
|
|
func reportCompletionOrStartNext() {
|
|
|
- prefetchQueue.async {
|
|
|
|
|
- if let resource = self.pendingResources.popFirst() {
|
|
|
|
|
- self.startPrefetching(resource)
|
|
|
|
|
- } else {
|
|
|
|
|
- guard self.tasks.isEmpty else { return }
|
|
|
|
|
- self.handleComplete()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if let resource = self.pendingResources.popFirst() {
|
|
|
|
|
+ startPrefetching(resource)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ guard tasks.isEmpty else { return }
|
|
|
|
|
+ handleComplete()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|