간단한 솔루션은이 작업을 비동기 적으로 수행하여 진행 상황을 업데이트하는 것입니다.
진행 상황보기를 만들고 시야에 추가하십시오.
코드를 배경 대기열로 발송하십시오
각 다운로드가 완료되면 진행 상황보기를 기본 대기열로 다시 발송합니다.
의사 코드에서는 모양이 될 것입니다
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];
});
}
});
점점 더 우아한 접근 방식이 있습니다.
동시 대기열을 사용하여 (위의 이미지를 일련의 다운로드하는 대신) 이미지를 다운로드하여 상당히 빠릅니다. 작동 대기열을 제안 할 수 있습니다
maxConcurrentCount
의5
, 동시성을 즐기려면 동시 요청 수의 iOS 한도를 초과하지 않도록하십시오.사용
NSURLConnectionDataDelegate
기반 다운로드NSData
방법initWithContentsOfURL
, 개별 다운로드 중에 임시 진행을 제공 할 수 있습니다. 보다 다운로드 관리자 또는 작업을 다운로드하십시오 예를 들어.사용 Afnetworking 또한 다운로드 진행 블록 기반 인터페이스를 제공합니다.
위의 1 점에서 동시 대기열을 사용하는 것이 좋습니다. 그래서 나는 그것을 벤치마킹하기로 결정했습니다. 저에게는 아래 의이 GCD 구현은 NSOperationQueue
그것을 따르는 구현.
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);
});
이에 NSOperationQueue
구현:
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];
결론, 당신이 사용하는 경우 NSOperationQueue
(GCD 동시 대기열에서도 할 수있는 동시성을 제공 할뿐만 아니라 동시 작업 수 (네트워크 운영의 경우 5 개 이하로 제한해야 함)를 쉽게 제어 할 수 있습니다). 상당한 성능 이점.
내가 제안한 바와 같이, 더 나은 것은 Afnetworking을 사용하는 것이며,이 작업은이 작전 큐 동시성 혜택뿐만 아니라 다른 이점도 즐길 수 있습니다.