0

I'm trying to build an app that will display a collection of magazines that can be downloaded and then read. What I want to happen is if the magazine isn't downloaded, a download will commence when a cell is tapped and a progressview will appear in the corresponding cell showing the download progress. I have subclassed UICollectionViewCelland added a UIProgressView property. So far, I've been able to check whether the file is downloaded and if it isn't, download it, and if it is, just open it using a PDF library called VFR Library. I can also update a progress view placed outside of the UICollectionViewCell but I can't update one placed within the UICollectionViewCell. Unfortunately, most of my logic for downloading and updating the progressview is within didSelectItemAtIndexPath:. I know this isn't elegant but my experience level isn't high enough that I can effectively develop my own classes to work together seamlessly. But once I figure this out I'll work on refining the code and abstracting things away a bit. Anyway, here's what I'm doing in didSelectItemAtIndexPath:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    IssueCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

    self.navBarLabel.hidden = YES;
    self.mainProgressView.hidden = NO;
    self.view.userInteractionEnabled = NO;
    //self.activityIndicator.hidden = NO;
    [self.activityIndicator startAnimating];            

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"issue%ld", (long)indexPath.row]]stringByAppendingPathExtension:@"pdf"];

    if ([[NSFileManager defaultManager]fileExistsAtPath:path])
    {
        ReaderDocument *document = [ReaderDocument withDocumentFilePath:path password:nil];
        if (document != nil)
        {
            //opens PDF for viewing
            ReaderViewController *readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
            readerViewController.delegate = self;
            readerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
            readerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
            [self presentViewController:readerViewController animated:YES completion:nil];
            self.mainProgressView.hidden = YES;
            self.navBarLabel.hidden = NO;
            self.view.userInteractionEnabled = YES;
            //self.activityIndicator.hidden = YES;
            [self.activityIndicator stopAnimating];
        }
    }
    else
    {
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlArray[indexPath.row]]];
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

        operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSLog(@"Successfully downloaded file to %@", path);
            ReaderDocument *document = [ReaderDocument withDocumentFilePath:path password:nil];
            if (document != nil)
            {
                //opens PDF for viewing
                ReaderViewController *readerViewController =       [[ReaderViewController alloc] initWithReaderDocument:document];
                readerViewController.delegate = self;
                readerViewController.modalTransitionStyle =       UIModalTransitionStyleCrossDissolve;
                readerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
                [self presentViewController:readerViewController animated:YES completion:nil];
                self.mainProgressView.hidden = YES;
                self.navBarLabel.hidden = NO;
                //self.activityIndicator.hidden = YES;
                self.view.userInteractionEnabled = YES;

                [self.activityIndicator stopAnimating];
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Download Failed" message:@"There was a problem downloading this issue" delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alertView show];
            self.mainProgressView.hidden = YES;
            self.navBarLabel.hidden = NO;
            [self.activityIndicator stopAnimating];
            //self.activityIndicator.hidden = YES;
            self.view.userInteractionEnabled = YES;
            NSLog(@"Error: %@", error);
        }];

        [operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {

            float percentDone =((float)((int)totalBytesWritten) / (float)((int)totalBytesExpectedToWrite));

            self.mainProgressView.progress = percentDone;
            [cell.progressView setProgress:percentDone];
            [self.collectionView reloadData];
            // [cell.progressView performSelectorOnMainThread:@selector(loadingProgress:) withObject:[NSNumber numberWithFloat:percentDone] waitUntilDone:NO];

            NSLog(@"Sent %lld of %lld bytes, %@", totalBytesWritten, totalBytesExpectedToWrite, path);
        }];

        [operation start];

    }



 }

So is there any way that I can update the progress view within a corresponding cell within this method or is there something else I need to do to get it to work? Thanks for any help you can give.

mike
  • 1,441
  • 2
  • 19
  • 31

2 Answers2

3

Well, I've finally solved my own problem. Apparently the problem was due to not fully understanding how to reference a particular item in a UICollectionView. All I had to do was create a method that actually did this and then call it in the "setDownloadProgressBlock:" method above. The method I wrote for this is:

 - (void)setProgressAtIndex:(NSInteger)index withProgress:(float)progress
{
    IssueCell *cell = (IssueCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
    [cell.progressView setProgress:0.0];
    [cell.progressView setProgress:progress];
}

The important line in this method is the first one where I grab a reference to the desired cell. This one actually grabs the cell that was tapped, whereas before I guess I was just referring to all the cells in general? I'm not too sure, but I would definitely appreciate it if someone had a better explanation.

This method was then called like so:

[self setProgressAtIndex:indexPath.row withProgress:percentDone];

Again, I did this inside the block in "setDownloadProgressBlock:". Hopefully this helps someone else in the future!

mike
  • 1,441
  • 2
  • 19
  • 31
0

Update your progress view on your main thread. Try using dispatch_sync(dispatch_get_main_queue()).

MichaelScaria
  • 1,560
  • 2
  • 16
  • 25
  • thanks for the response. Unfortunately, I couldn't get that to work. I'm not too familiar with GCD but I tried doing what you said within the completion blocks of the code I posted and the app gets hung up when a cell is tapped. Thanks again though – mike May 29 '13 at 14:15