2014-01-26 2 views
2

요구 사항 :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 위의 방법에서, 처리기 블록을 호출하려고하면 앱이 다운됩니다.

지금 내 질문은 :

  1. 왜 didFinishDownloadingToURL에 나는 setupAndStartDownloadTaskForProduct에서 시작 하나보다, 다른 식별자는 무엇입니까?

  2. 이것이 예상되는 동작이면 내 요구 사항을 구현하는 가장 좋은 방법은 무엇입니까?

+0

'self.session'에 대한 코드를 게시 할 수 있습니까? – Eric

답변

-1

느린로드 이미지의 this post을 (를) UITableView에 체크 아웃 했습니까?

아마도 UICollectionView에 맞게 사용자 정의 할 수 있습니다.

희망이 도움이됩니다.

+0

그 링크는 포스터가 사용했던 것에서부터 한 발 뒤로 물러나 있습니다. –

0

사용중인 taskIdentifier는 분명 NSUInteger입니다. 당신이하고있는 것은 문자 그대로의 바로 가기 키와 같은의 NSNumber을 사용하고 있습니다 :

NSNumber * key = @(downloadTask.taskIdentifier);

문제는 사전에 키있는 NSString 이외의 것을 사용하는 것이 좋은 생각이라는 것이다. 당신이 한 일은 동일한 값을 가지고 있지만 -isEqual :이 true로 평가되는 것을 보장하지 않는 NSNumber 객체를 생성하는 것입니다. 대신의 NSNumber 키를 사용

, 문자열로 키를 변환 :

NSString * key = [NSString stringWithFormat:@"%d", downloadTask.taskIdentifier];

그런 다음 사전 해시가 작동합니다.