요구 사항 :NSURLSessionDownloadTask 동시 다운로드 또한 예상대로 작동하지 않는, 응용 프로그램 배경에서 지원
내가보기 컨트롤러 클래스,있는 내가 Collection 뷰를 표시하고 있습니다. 각 셀에 대해 이미지가 이미 로컬에 존재하는지 여부를 확인합니다. 존재하지 않으면 서버에서 이미지를 다운로드하고 동일하게 표시하려고합니다.
구현 :
- (void)setupAndStartDownloadTaskForProduct:(Products *)aProduct withCompletionHandler:(DownloadedCompletionHandler)completionHandler andFailureHandler:(DownloadedFailureHandler)failureHandler
{
NSString *completeImagePath = [kBasePath stringByAppendingPathComponent:aProduct.imageRelativePath];
NSURL *downloadURL = [NSURL URLWithString:completeImagePath];
if (!self.session) {
[self setUpSession];
}
NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:downloadURL];
NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:downloadRequest];
NSDictionary *downloadInfoDict = @{kSuccessHandlerKey: [completionHandler copy], kFailureHandlerKey: [failureHandler copy]};
self.downloadTasks[@(downloadTask.taskIdentifier)] = downloadInfoDict;
// resuming the download task
[downloadTask resume];
}
:
세션 컨트롤러 클래스에서- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// retrieving associated product
Products *aProduct = [self.fetchedResultsController objectAtIndexPath:indexPath];
UICollectionViewCell* newCell = [self.collectionView dequeueReusableCellWithReuseIdentifier:kProductIconIdentifier forIndexPath:indexPath];
// setup of image view and cell label
UIImageView *cellImageView = (UIImageView *)[collectionView viewWithTag:kImageViewTag];
cellImageView.contentMode = UIViewContentModeScaleAspectFill;
UILabel *cellLabel = (UILabel *)[newCell viewWithTag:klabelTag];
// assigning value to cell label and image view
NSString *productImageLocalPath = aProduct.imageLocalPath;
if ([[NSFileManager defaultManager] fileExistsAtPath:productImageLocalPath]) {
// file exists at local path :-)
// means less fun :-(
cellImageView.image = [UIImage imageWithContentsOfFile:productImageLocalPath];
}
else
{
UIActivityIndicatorView *downloadActivityIndicator = (UIActivityIndicatorView *)[newCell viewWithTag:kActivityIndicator];
downloadActivityIndicator.hidden = NO;
[downloadActivityIndicator startAnimating];
// file does not exist at local path :-(
// means more fun :-)
[self.sessionController setupAndStartDownloadTaskForProduct:aProduct withCompletionHandler:^(NSString * tempLocalPath){
// download was successful
NSData *imageData = [[NSData alloc] initWithContentsOfFile:tempLocalPath];
[imageData writeToFile:productImageLocalPath atomically:YES];
cellImageView.image = [UIImage imageWithData:imageData];
[downloadActivityIndicator stopAnimating];
} andFailureHandler:^{
cellImageView.image = nil;
[downloadActivityIndicator stopAnimating];
}];
}
// setting values
cellLabel.text = aProduct.imageName;
return newCell;
}
, 나는 새로운 다운로드 작업을 시작하는 방법은 아래에있다 : 아래
이 같은 코드입니다 위의 메서드에서는 successHandler 및 failureHandler 블록을 사전에 저장하고 해당 작업 ID를 사용하여 다운로드 작업과 매핑합니다. ifier.
아래는 didFinishDownloadingToURL 방법의 구현 :
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
dispatch_async(dispatch_get_main_queue(), ^{
// invoking success block
DownloadedCompletionHandler successCompletionHandler = self.downloadTasks[@(downloadTask.taskIdentifier)][kSuccessHandlerKey];
successCompletionHandler([location path]);
// removing download task key-value pair from dictionary
[self.downloadTasks removeObjectForKey:@(downloadTask.taskIdentifier)];
});
}
내 문제가 - 가끔있는 successCompletionHandler가 전무로 얻을 수 있기 때문에, setupAndStartDownloadTaskForProduct에서 시작한 것과 다른 식별자를 반환 downloadTask 위의 방법에서, 처리기 블록을 호출하려고하면 앱이 다운됩니다.
지금 내 질문은 :
왜 didFinishDownloadingToURL에 나는 setupAndStartDownloadTaskForProduct에서 시작 하나보다, 다른 식별자는 무엇입니까?
이것이 예상되는 동작이면 내 요구 사항을 구현하는 가장 좋은 방법은 무엇입니까?
'self.session'에 대한 코드를 게시 할 수 있습니까? – Eric