You should change your model such that it doesn't matter what order the images are downloaded. For example, you have your array of image URL strings:
var imageURLs: [String]
So, your NSData
should be stored in a dictionary (or NSCache
) keyed by that URL string:
var imageData = [String: NSData]()
Then when you download the data, you can update this dictionary:
self.imageData[imageURL] = dtA
Then, when you need to retrieve this data later, you can use the imageURL, e.g.:
let data = imageData[imageURLs[index]]
Or you could define it as a [Int: NSData]
and use the number index as the key. But the idea is that you can use a dictionary, and then the order you receive the responses doesn't matter, but you still enjoy the performance benefit of doing concurrent requests.
What I'd suggest would be something like:
var imageData = [String: NSData]()
@IBAction func didClickOnStart(sender: AnyObject) {
queue.cancelAllOperations()
let completionOperation = NSBlockOperation() {
print("all done")
}
for (index, imageURL) in imageURLs.enumerate() {
let operation = DataOperation(session: session, urlString: imageURL) { data, response, error in
guard let data = data where error == nil else { return }
guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else { return }
NSOperationQueue.mainQueue().addOperationWithBlock {
self.imageData[imageURL] = data
}
print("JPEG download\(index)")
}
completionOperation.addDependency(operation)
queue.addOperation(operation)
}
NSOperationQueue.mainQueue().addOperation(completionOperation)
}
And then access it like so:
if let data = imageData[imageURLs[index]], let image = UIImage(data: data) {
// use `image` here
}
Or
var imageData = [Int: NSData]()
@IBAction func didClickOnStart(sender: AnyObject) {
queue.cancelAllOperations()
let completionOperation = NSBlockOperation() {
print("all done")
}
for (index, imageURL) in imageURLs.enumerate() {
let operation = DataOperation(session: session, urlString: imageURL) { data, response, error in
guard let data = data where error == nil else { return }
guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else { return }
NSOperationQueue.mainQueue().addOperationWithBlock {
self.imageData[index] = data
}
print("JPEG download\(index)")
}
completionOperation.addDependency(operation)
queue.addOperation(operation)
}
NSOperationQueue.mainQueue().addOperation(completionOperation)
}
And access it like so:
if let data = imageData[index], let image = UIImage(data: data) {
// use `image` here
}
Note, ImageNetworkOperation
is just calling DataOperation
to get the NSData
, and then converting it to a UIImage
. If you really want the original NSData
, I'd suggest bypassing ImageNetworkOperation
and just calling DataOperation
directly, like shown above.