0

I've already asked the same question about saving pressed button state and I thought that I should do in the same way to save progress state on cells but my tries are unsuccessful.

What I'm doing now: I select some UICollectionViewCell's and then press "download" button and then downolad action starts. Every cell I selected shows UIProgressView and everything is ok untill I scroll my UICollectionView up or down. When I do it another cells have progress view too but they mustn't! I know that I must save indexPath of selected cells in NSMutableArray and then in cellForItemAtIndexPath check if current cell indexPath is in my array and then show or hide my cell's subviews. I do that but it only works with cell selection! What should I do to save progress view state on each cell this progress really there?

Here is my code:

In cellForItemAtIndexPath:

 NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
{

    cell.selectedBG.hidden = NO;
    cell.selectedImg.hidden = NO;


}
else
{

    cell.selectedBG.hidden = YES;
    cell.selectedImg.hidden = YES;
    cell.progressView.hidden = YES;


}

In didSelectItemAtIndexPath:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
...
        // Add the selected item into the array
        [selectedIds addObject:selectedId];
        [selectedVideos addObject:selectedVideo];
        AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
        NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
        if ( ![selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
        {
            [selecedCellsArray addObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
            collectionCell.selectedBG.hidden = NO;
            collectionCell.selectedImg.hidden = NO;
            [collectionCell setSelected:YES];
        }
    }
}

In didDeselectItemAtIndexPath:

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
   ...

    // Delete the selected item from the array
    [selectedIds removeObject:selectedId];
    [selectedVideos removeObject:selectedVideo];
    AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
    NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
    if ( [selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
    {
        [selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
        collectionCell.selectedBG.hidden = YES;
        collectionCell.selectedImg.hidden = YES;
        [collectionCell setSelected:NO];

    }
}

And this is how I show my progress:

-(NSString *)progress:(long long )val1 : (long long )val2 : (AVMVideoCell *)cell : (NSString *)name : (NSIndexPath *)path{

float progress = ((float)val1) / val2;
NSString *prog = [[NSNumber numberWithFloat:progress*100] stringValue];
if (prog != nil){
    if(cell.isSelected){
    cell.selectedImg.hidden = YES;
    cell.progressView.hidden = NO;
    }
}


NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)path.row];
if ( [selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]])
{
[cell.progressView setProgress:progress animated:YES];
}

if([prog intValue]==100){
    cell.progressView.hidden = YES;

}
return prog;
}

EDIT: AVMVideoCell.m

#import "AVMVideoCell.h"


@implementation AVMVideoCell
{
    NSString *fullUrl;
}
@synthesize imageView;
@synthesize selectedBG;
@synthesize progressLabel;
@synthesize progressView;
@synthesize selectedImg;
@synthesize progLayer;

-(void) setVideo:(AVMDataStore *)video {
if(_video != video) {
    _video = video;
}
NSString *durString = [NSString stringWithFormat:@"%@",[self timeFormatted:_video.duration]];
if((_video.filePreview != nil) && ![_video.filePreview isEqualToString:@""]){
fullUrl = [NSString stringWithFormat:@"http://example.com%@",_video.filePreview];
}

NSURL *imgURL = [NSURL URLWithString:fullUrl];

[self.imageView setImageWithURL:imgURL
               placeholderImage:[UIImage imageNamed:@"yesterday.png"] options:0 usingActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
self.duration.text = durString;

}

- (NSString *)timeFormatted:(int)totalSeconds
{

int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;

return [NSString stringWithFormat:@"%02d:%02d:%02d",hours, minutes, seconds];
}
@end

EDIT 2: Explanation about progress My progressView is not an IBOutlet it's a @property (nonatomic,strong) UIProgressView *progressView; (AVMVideoCell.h)

I allocate and initialize it in cellForItemAtIndexPath:

cell.progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0,0, 150.0f, 1.0f)];
cell.progressView.trackTintColor = [UIColor colorWithWhite:255 alpha:0.5f];
cell.progressView.progressTintColor = [UIColor whiteColor];
[cell.progLayer addSubview:cell.progressView];
cell.progressView.hidden = YES;
cell.progressView.tag = indexPath.row+500;

This is where I call progress change showing:

-(void)downloadStart:(NSString*)fileUrl : (NSString*)name : (AVMVideoCell *) cell : (NSIndexPath *)path{

NSURL *URL = [NSURL URLWithString:fileUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSString *fileName = [NSString stringWithFormat:@"%@.mp4",name]; //set full file name to save
AFHTTPRequestOperation *downloadRequest = [[AFHTTPRequestOperation alloc] initWithRequest:request]; //create download request
[downloadRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSData *data = [[NSData alloc] initWithData:responseObject];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *pathToFile = [NSString stringWithFormat:@"%@/%@", [paths firstObject],fileName]; // path to 'Documents'

    NSString *pathOfFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:pathOfFile append:NO];
   BOOL success =  [data writeToFile:pathToFile atomically:YES];
    if(success){
         [self checkIfExists:name : cell :path];
    }

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"file downloading error : %@", [error localizedDescription]);
    UIAlertView * alert=[[UIAlertView alloc]initWithTitle:@"Error" message:[NSString stringWithFormat:@"%@",error] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil ];
    [alert show];
    cell.progressView.hidden = YES;

}];
// Step 5: begin asynchronous download
[downloadRequest start];
[downloadRequest setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {

    [self progress:totalBytesRead :totalBytesExpectedToRead :cell :name : path]; //here I pass val1 and val 2


  }];

}

When I select an items in collection view, I gather their model's objects, get each id and make array of urls, then in for..in loop i pass urls one by one and then start async download. You can see how I download and call progress method above.

vendettacore
  • 1,439
  • 1
  • 13
  • 28

2 Answers2

1

You can create class for cell's models, store these models in array in your viewController and use them to get/set all states from/for cells.
Something like this:

@interface CellModel : NSObject
    @property(nonatomic) BOOL selected;
    @property(nonatomic) NSUInteger progress;
@end

In viewController:

@interface MyViewController () <UITableViewDataSource, UITableViewDelegate>
    @property (nonatomic) NSArray* models;
@end
Andrew Romanov
  • 4,774
  • 3
  • 25
  • 40
1

I need to know if you have a reuse issue or a model issue.

So first try this :

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
...

    if (![selectedIds.containsObject:selectedId])
    {
        // Add the selected item into the array
        [selectedIds addObject:selectedId];
        [selectedVideos addObject:selectedVideo];
        AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
        NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
        if ( ![selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
        {
            [selecedCellsArray addObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
            collectionCell.selectedBG.hidden = NO;
            collectionCell.selectedImg.hidden = NO;
            [collectionCell setSelected:YES];
        }
    }
    else {
    // Delete the selected item from the array
    [selectedIds removeObject:selectedId];
    [selectedVideos removeObject:selectedVideo];
    AVMVideoCell *collectionCell = (AVMVideoCell*)[collectionView cellForItemAtIndexPath:indexPath];
    NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
    if ( [selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
    {
        [selecedCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
        collectionCell.selectedBG.hidden = YES;
        collectionCell.selectedImg.hidden = YES;
        [collectionCell setSelected:NO];
    }
}

and remove the didDeselect delegate.

Let me know what happens then.

EDIT :

Ok try this now:

// Lazy instantiation of the progressView
- (UIProgressView *)progressView
{
    if (!_progressView)
    {
        _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0,0, 150.0f, 1.0f)];
        _progressView.trackTintColor = [UIColor colorWithWhite:255 alpha:0.5f];
        _progressView.progressTintColor = [UIColor whiteColor];
        _progressView.hidden = YES;

        [self.contentView addSubview:_progressView];
    }

    return _progressView;
}


// Here we remove the progressView on reuse
-(void)prepareForReuse
{
    [super prepareForReuse];

    [self.progressView removeFromSuperview];
    self.progressView = nil;
}

Also remove what you did with the progressView with in the cellForItemAtIndexPath method.

Kujey
  • 1,122
  • 6
  • 17
  • nothing has changed. besides now I must press 2 times to select/deselect my cell. I'm sure that I've reuse issue – vendettacore Feb 19 '15 at 16:54
  • Is your progressview an iboutlet ? Where do you call progress:val1:val2 ? – Kujey Feb 19 '15 at 17:09
  • I made a post a while ago about this kind of issues : http://stackoverflow.com/questions/23801418/uicollectionview-adding-image-to-a-cell/23802296#23802296 . Check it if you want more informations – Kujey Feb 19 '15 at 18:02
  • wow! amazing! thank you very much! works like a charm!) should I do the same way if my progressview is an `IBOutlet`? – vendettacore Feb 19 '15 at 18:18
  • No you don't need to do it for iboutlets – Kujey Feb 19 '15 at 18:26