保存 UICollectionViewCell 进度状态

Posted

技术标签:

【中文标题】保存 UICollectionViewCell 进度状态【英文标题】:Save UICollectionViewCell progress state 【发布时间】:2015-02-19 11:04:02 【问题描述】:

我已经问过关于保存按下按钮状态的相同问题,我认为我应该以同样的方式保存单元格上的进度状态,但我的尝试不成功。

我现在在做什么:我选择一些UICollectionViewCell's,然后按“下载”按钮,然后开始下载操作。我选择的每个单元格都显示UIProgressView,一切正常,直到我向上或向下滚动UICollectionView。当我这样做时,另一个单元格也有进度视图,但它们不能!我知道我必须将选定单元格的indexPath 保存在NSMutableArray 中,然后在cellForItemAtIndexPath 中检查当前单元格 indexPath 是否在我的数组中,然后显示或隐藏我的单元格的子视图。我这样做了,但它只适用于单元格选择!我应该怎么做才能在每个单元格上保存进度视图状态,这个进度真的在那里?

这是我的代码:

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;



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];
        
    

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];

    

这就是我展示我的进步的方式:

-(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;

编辑: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

编辑 2:关于进度的说明 我的progressView 不是IBOutlet 它是@property (nonatomic,strong) UIProgressView *progressView; (AVMVideoCell.h)

我在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;

这就是我所说的进度变化显示:

-(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


  ];


当我在集合视图中选择一个项目时,我收集他们模型的对象,获取每个 id 并制作 url 数组,然后在 for..in 循环中我一个接一个地传递 url,然后开始异步下载。您可以在上面看到我如何下载和调用进度方法。

【问题讨论】:

你能粘贴整个 AVMVideoCell.m 代码吗? @Kujey 当然,看看我的编辑 【参考方案1】:

我需要知道您是否有重复使用问题或模型问题。

所以先试试这个:

- (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];
    

并删除 didDeselect 委托。

让我知道接下来会发生什么。

编辑:

好的,现在试试这个:

// 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;

同时删除您在 cellForItemAtIndexPath 方法中对 progressView 所做的操作。

【讨论】:

什么都没有改变。除此之外,我必须按 2 次才能选择/取消选择我的单元格。我确定我有重用问题 您的进度视图是 iboutlet 吗?你在哪里调用 progress:val1:val2 ? 我不久前发了一篇关于此类问题的帖子:***.com/questions/23801418/…。如果您想了解更多信息,请检查它 哇!惊人的!非常感谢!像魅力一样工作!)如果我的进度视图是IBOutlet,我应该这样做吗? 不,你不需要为 iboutlets 这样做【参考方案2】:

您可以为单元格的模型创建类,将这些模型存储在视图控制器中的数组中,并使用它们从单元格获取/设置所有状态。 像这样的:

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

在视图控制器中:

@interface MyViewController () <UITableViewDataSource, UITableViewDelegate>
    @property (nonatomic) NSArray* models;
@end

【讨论】:

那么我需要在我的自定义单元类中实现这个模型吗? @vendettacore 是的,您可以在出列时将该模型传递给每个单元格。然后,如果您需要更新进度,您可以抓取所有可见单元格并更新屏幕上可见单元格的进度。 我认为更好的是使用单独的文件来实现 CellModel

以上是关于保存 UICollectionViewCell 进度状态的主要内容,如果未能解决你的问题,请参考以下文章

从 UICollectionViewCell 访问保存在 UIViewController 中的变量?

如何将 UITableViewCell 内的 UICollectionViewCell 的选定索引路径保存到数组中?

手势识别器在其他 UICollectionViewCell 内的 UICollectionView 上不起作用

使用 UICollectionViewCell 内的 Textfield 更新标签

检测 iOS UICollectionCell 何时离开屏幕

Swift 检测 UICollectionViewCell 是不是被拖到另一个 UICollectionViewCell 之上