问题
I have array of photos that needs to be downloaded, but download function can download only one photo at a time. I neeed to make sure that download function is completed before I call it for other photo. I create .initialyInactive DispatchQueue and queue is activated in completion block of download function. This is woking, and photos are downloaded, but my question is how to cancel download process? Can I somehow to remove not activated queues?
My code logic looks something like this..
func downloadPhoto(photo: Photo, completion: (_ success: Bool) -> Void) {
... completion(true) ..
}
for photo in photos {
let queue = DispatchQueue(label: "Download queue\(counter)", qos: .userInitiated, attributes: .initiallyInactive)
self.inactiveQueues[counter] = queue
queue.async {
self.downloadPhoto(photo: photo) { (success) in
nextQueue?.activate()
if success {
...
} else {
...
}
}
}
Ant other solution to my problem is great too. Thanks.
回答1:
There are several options:
Historically we’d use a custom, asynchronous,
Operation
subclass. See https://stackoverflow.com/a/38469350/1271826 (or see https://stackoverflow.com/a/48104095/1271826 for alternateAsynchronousOperation
implementation). That gives us a cancelable operation and we can easily control the degree of concurrency.If you want to download them one at a time, you could set the queue’s
maxConcurrentOperationCount
to 1. Then you can just add your download operations to a singleOperationQueue
, and if you want to cancel them, you’d call queue.cancelAllOperations().If you are targeting iOS 13 and later, Combine makes this even easier. See https://stackoverflow.com/a/61195234/1271826 for example of downloading a series of images using Combine (both sequentially as well as with a controlled degree of concurrency).
All of this having been said, I’d encourage you to reconsider the choice to download the images sequentially. In my random test, increasing the max allowed concurrency to 6 resulted in downloads that were, overall, twice as fast as the serial behavior.
来源:https://stackoverflow.com/questions/60875215/remove-initiallyinactive-queue