La solution simple consiste à le faire de manière asynchrone, à mettre à jour la vue de progression au fur et à mesure:
Créez la vue de progression et ajoutez-la à votre vue
Envoyez votre code à une file d'attente d'arrière-plan
À mesure que chaque téléchargement se termine, envoyez la mise à jour de la vue de progression vers la file d'attente principale
Dans le code pseudo, cela ressemblerait à
UIProgressView *progressView = [[UIProgressView alloc] init];
// configure the progress view and add it to your UI
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i=0; i<[array count]; i++)
{
NSError *error;
NSArray *ipaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *idocumentsDir = [ipaths objectAtIndex:0];
NSString *idataPath = [idocumentsDir stringByAppendingPathComponent:@"File"];
NSLog(@"idataPath:%@",idataPath);
//Create folder here
if (![[NSFileManager defaultManager] fileExistsAtPath:idataPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:idataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
// Image Download here
NSString *fileName = [idataPath stringByAppendingFormat:@".jpg"];
NSLog(@"imagePathDOWNLOAD:%@",fileName);
_imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[array objectAtIndex:i]]];
[_imgData writeToFile:fileName atomically:YES];
// now dispatch any UI updates back to the main queue
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress: (CGFloat) (i + 1.0) / [array count] animated:YES];
tempImg.image = [UIImage imageWithData:_imgData];
});
}
});
Il existe également toute une série d'approches de plus en plus élégantes:
Utilisez la file d'attente simultanée (plutôt que ce qui précède, qui télécharge les images en série) pour télécharger les images, qui seront beaucoup plus rapidement. Je pourrais suggérer une file d'attente d'opération avec
maxConcurrentCount
de5
, pour profiter de la concurrence, mais assurez-vous de ne pas dépasser la limite iOS dans le nombre de demandes simultanées.Utilisation
NSURLConnectionDataDelegate
téléchargement basé plutôt que leNSData
méthodeinitWithContentsOfURL
, qui peut offrir des progrès provisoires pendant les téléchargements individuels. Voir Gestionnaire de téléchargement ou opération de téléchargement pour des exemples.Utilisation Afnetworking qui fournit également une interface basée sur le bloc de progression.
Ci-dessus, au point 1, j'ai suggéré d'envisager d'utiliser une file d'attente simultanée, j'ai donc décidé de le comparer. Pour moi, cette implémentation GCD ci-dessous était 3-4 fois plus lente que le NSOperationQueue
implémentation qui le suit.
Voici la mise en œuvre de GCD:
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
UIProgressView *progressView = [self addProgressView];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSInteger downloadSuccessCount = 0;
NSInteger downloadFailureCount = 0;
NSString *idataPath = [self createDownloadPath];
for (int i = 0; i < [array count]; i++)
{
// Image Download here
NSString *filename = [self pathForItem:i array:array folder:idataPath];
NSURL *url = [self urlForItem:i array:array];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *image = nil;
if (data)
image = [UIImage imageWithData:data];
if (image) {
downloadSuccessCount++;
[data writeToFile:filename atomically:YES];
} else {
downloadFailureCount++;
}
// now dispatch any UI updates back to the main queue
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress: (CGFloat) (downloadSuccessCount + downloadFailureCount) / [array count] animated:YES];
// update the image in the UI if you want
[UIView transitionWithView:self.imageView duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
tempImg.image = image;
} completion:nil];
});
}
NSLog(@"Completed in %.1f seconds", CFAbsoluteTimeGetCurrent() - start);
});
pour ça NSOperationQueue
la mise en oeuvre:
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
UIProgressView *progressView = [self addProgressView];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 5;
NSString *idataPath = [self createDownloadPath];
self.downloadSuccessCount = 0;
self.downloadFailureCount = 0;
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Completed in %.1f seconds", CFAbsoluteTimeGetCurrent() - start);
}];
for (int i = 0; i < [array count]; i++)
{
NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
// Image Download here
NSString *filename = [self pathForItem:i array:array folder:idataPath];
NSURL *url = [self urlForItem:i array:array];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = nil;
if (data)
image = [UIImage imageWithData:data];
if (image)
[data writeToFile:filename atomically:YES];
// now dispatch any UI updates back to the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
if (image) {
self.downloadSuccessCount++;
// update the image in the UI if you want, though this slows it down
[UIView transitionWithView:self.imageView duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
tempImg.image = image;
} completion:nil];
}
else
self.downloadFailureCount++;
[progressView setProgress: (CGFloat) (self.downloadSuccessCount + self.downloadFailureCount) / [array count] animated:YES];
}];
}];
[queue addOperation:operation];
[completionOperation addDependency:operation];
}
[queue addOperation:completionOperation];
Conclusion, si vous utilisez NSOperationQueue
(qui non seulement accorde une concurrence, ce que vous pouvez également faire dans une file d'attente simultanée GCD, mais il vous permet également de contrôler facilement le nombre d'opérations simultanées (que vous devez limiter à cinq ou moins pour les opérations de réseau)), vous profiterez d'un Avantage de performance significatif.
Encore mieux, comme je l'ai suggéré, serait d'employer Afnetworking, dans lequel vous appréciez non seulement cet avantage concurrentiel de file d'attente, les deux avantages sociaux.