UICollectionView - 在其他单元格中复制的子视图实例

时间:2013-08-16 15:25:47

标签: ios objective-c uicollectionview uicollectionviewcell uiprogressview

首先,我的应用程序的粗略描述是特定组织的杂志库应用程序

  1. 我有一个定制的UICollectionViewCell完成了故事板原型。在原型中有3个视图 - UIImageView UILabel UILabel
  2. 此外,在 collectionView:cellForItemAtIndexPath: 中,我创建了一个

    的实例
    • UIButton (操作:@selector(downloadButtonTapped :))

    • UIProgressView ,其 tag=indexPath.item hidden=YES 。然后,我将UIProgressView添加到相同索引的数组 - self.progressViewArray ,与单元格的 indexPath.item 相同
  3. 每次点击特定单元格的“下载”按钮并调用 downloadButtonTapped: 时,我都会获得单元格 发件人的superview的superview的 ,即单元格。然后我检查[self.progressViewArray[indexPath.item] tag] == indexPath.item。如果条件满足,则执行 [self.progressViewArray[indexPath.item] setHidden:NO]

  4. 我有22个对象的数据源,因此,我有22个单元格。到目前为止,一切都像我想要的那样。即使我在视图中滚动单元格(出列)并返回视图(再循环),UIProgressView仍然存在。

    问题:

    progressView也会重新出现在其他单元格中!例如。如果我点击单元格3的“下载”按钮,UIProgressView正确显示在该单元格中,单元格10和19也显示“重复”UIProgressView 。此问题也适用于其他单元格。例如。当我点击单元格20的“下载”时,我向上滚动,我看到单元格12和4的加载UIProgressViews也一样,就像那些杂志也被下载一样。

    为什么我提到相同是因为我有一个setDownloadProgressBlock来更新UIProgressViews的进度以及单元格3,10和19的进度UIProgressViews正在一起进行。

    我真的希望我能在这里找到一些帮助,因为我已经在这个问题上花了很多天的时间来绞尽脑汁。

    P.S。编辑下面的调试尝试。


    以下是涉及的方法:

    的CollectionView:cellForItemAtIndexPath:

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *identifier = @"Cell";
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    
        // * ========== Configure Cell ========== *
        // Initialisation of UIImageViews and UILabels here.
        // ...
    
        // CREATION OF CELL'S DOWNLOADBUTTON
        UIButton *downloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [downloadButton addTarget:self action:@selector(downloadButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
        [downloadButton setFrame:CGRectMake(178, 197, 140, 44)];
        [downloadButton setTitle:[self setDownloadButtonTitleAtIndexPath:indexPath.item] forState:UIControlStateNormal];
        [downloadButton setTitle:@"Downloading..." forState:UIControlStateDisabled];
        [downloadButton setEnabled:YES];
        [downloadButton setUserInteractionEnabled:YES];
        [downloadButton setTag:indexPath.item];
        [cell.contentView addSubview:downloadButton];
    
    
        // CREATION OF CELL'S UIPROGRESSVIEW
        UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
        [progressView setFrame:CGRectMake(20, 248, 150, 9)];
        [progressView setHidden:YES];
        [progressView setTag:indexPath.item];
        [self.progressViewArray addObject:progressView];
    
        // This chunk is to prevent creating new progress views when the cells are being recycled.
        if ([self.progressViewArray[indexPath.item] tag] != progressView.tag)
        {
            [self.progressViewArray replaceObjectAtIndex:indexPath.item withObject:progressView];
        }
    
        [cell.contentView addSubview:self.progressViewArray[indexPath.item]];
        // * ---------- Configure Cell ---------- *
    
        return  cell;
    }
    

    downloadButtonTapped:

    - (IBAction)downloadButtonTapped:(id)sender
    {
        // Get the indexPath of tapped row.
        UICollectionViewCell *cell = (UICollectionViewCell *)[[sender superview] superview];
        NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
    
        // If file does not exist.
        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
        {
            // SHOW THE CELL'S HIDDEN UIPROGRESSVIEW
            if ([self.progressViewArray[indexPath.item] tag] == indexPath.item)
            {
                [self.progressViewArray[indexPath.item] setHidden:NO];
            }
    
    
            // AFHTTPRequestionOperation code here...
    
            // Track download progress.
            [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
             {
                 for (UIProgressView *progressView in self.progressViewArray)
                 {
                     if (progressView.tag == indexPath.item)
                     {
                         [progressView setProgress:(float) totalBytesRead / totalBytesExpectedToRead];
                     }
                 }
             }];
    
            // Post download codes etc ...
    
            [operation start];
        }
    }
    

    感谢您的时间。我很感激......

    编辑:

    作为另一个调试尝试,我在NSLog(@"%@ at indexPath #%d", self.progressViewArray[indexPath.item], indexPath.item);之前做了一个return cell;,只是为了确认只有被攻击的单元格的UIProgressView受到影响( setHidden = NO ),实际上它是

    点按了单元格3的下载按钮滚动到底部,然后返回到顶部集合,照常查看好像单元格10和19的progressViews也是活动的,这就是我记录的内容。如您所见,在下载处于活动状态时,日志显示只有单元格3的progressView(tag = 3)是( setHidden = NO 。单元格10和19仍然隐藏/不受影响。但我不明白为什么我在那里看到一个活跃的进展。

    这是日志:

    2013-08-17 10:59:33.179 SFCCA[22885:907] <UIProgressView: 0x1c5bca00; frame = (20 248; 150 9); hidden = YES; opaque = NO; layer = <CALayer: 0x1c5d1000>> at indexPath #0
    2013-08-17 10:59:33.187 SFCCA[22885:907] <UIProgressView: 0x1c59c7c0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 1; layer = <CALayer: 0x1c5bb310>> at indexPath #1
    2013-08-17 10:59:33.193 SFCCA[22885:907] <UIProgressView: 0x1c5aa1f0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 2; layer = <CALayer: 0x1c5aa270>> at indexPath #2
    2013-08-17 10:59:33.201 SFCCA[22885:907] <UIProgressView: 0x1c5b9860; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 3; layer = <CALayer: 0x1c5b9a30>> at indexPath #3
    2013-08-17 10:59:33.207 SFCCA[22885:907] <UIProgressView: 0x1c5aa670; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 4; layer = <CALayer: 0x1c5b8d60>> at indexPath #4
    2013-08-17 10:59:33.214 SFCCA[22885:907] <UIProgressView: 0x1c5b51d0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 5; layer = <CALayer: 0x1c5b5270>> at indexPath #5
    
    // Here, I have tapped cell 3's "Download" button.
    // Notice that at the bottom of the log, when I have scrolled off cell 3 and back, the log shows that the progressView (tag=3) in cell 3 is hidden=NO
    2013-08-17 10:59:43.389 SFCCA[22885:907] {downloadButtonTapped} - File does not exist. Download then read PDF.
    2013-08-17 10:59:43.929 SFCCA[22885:907] <UIProgressView: 0x1c5d5a10; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 6; layer = <CALayer: 0x1c5b4420>> at indexPath #6
    2013-08-17 10:59:43.938 SFCCA[22885:907] <UIProgressView: 0x1c5cd8e0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 7; layer = <CALayer: 0x1c5b68d0>> at indexPath #7
    2013-08-17 10:59:44.216 SFCCA[22885:907] <UIProgressView: 0x1d8c3b90; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 8; layer = <CALayer: 0x1d8c3c30>> at indexPath #8
    2013-08-17 10:59:44.223 SFCCA[22885:907] <UIProgressView: 0x1c5e08d0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 9; layer = <CALayer: 0x1c5b9330>> at indexPath #9
    2013-08-17 10:59:44.600 SFCCA[22885:907] <UIProgressView: 0x1d8c9aa0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 10; layer = <CALayer: 0x1d8c9480>> at indexPath #10
    2013-08-17 10:59:44.607 SFCCA[22885:907] <UIProgressView: 0x1d8cb590; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 11; layer = <CALayer: 0x1d8cb4b0>> at indexPath #11
    2013-08-17 10:59:45.160 SFCCA[22885:907] <UIProgressView: 0x1d8b9e20; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 12; layer = <CALayer: 0x1d8a6140>> at indexPath #12
    2013-08-17 10:59:45.171 SFCCA[22885:907] <UIProgressView: 0x1d8cc060; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 13; layer = <CALayer: 0x1d8ca870>> at indexPath #13
    2013-08-17 10:59:45.813 SFCCA[22885:907] <UIProgressView: 0x1d88dc10; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 14; layer = <CALayer: 0x1d88dc90>> at indexPath #14
    2013-08-17 10:59:45.822 SFCCA[22885:907] <UIProgressView: 0x1d8cc9e0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 15; layer = <CALayer: 0x1d872110>> at indexPath #15
    2013-08-17 10:59:46.154 SFCCA[22885:907] <UIProgressView: 0x1c5ed300; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 16; layer = <CALayer: 0x1c5ed280>> at indexPath #16
    2013-08-17 10:59:46.162 SFCCA[22885:907] <UIProgressView: 0x1c5eeae0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 17; layer = <CALayer: 0x1c5eea00>> at indexPath #17
    2013-08-17 10:59:46.652 SFCCA[22885:907] <UIProgressView: 0x1c5ee0f0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 18; layer = <CALayer: 0x1c5e35f0>> at indexPath #18
    2013-08-17 10:59:46.660 SFCCA[22885:907] <UIProgressView: 0x1c5efc70; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 19; layer = <CALayer: 0x1c5ee320>> at indexPath #19
    2013-08-17 10:59:46.903 SFCCA[22885:907] <UIProgressView: 0x1c5e8b30; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 20; layer = <CALayer: 0x1c5e4aa0>> at indexPath #20
    2013-08-17 10:59:46.914 SFCCA[22885:907] <UIProgressView: 0x1c5e8fd0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 21; layer = <CALayer: 0x1c5e7e50>> at indexPath #21
    2013-08-17 10:59:48.583 SFCCA[22885:907] <UIProgressView: 0x1d88dc10; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 14; layer = <CALayer: 0x1d88dc90>> at indexPath #14
    2013-08-17 10:59:48.590 SFCCA[22885:907] <UIProgressView: 0x1d8cc9e0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 15; layer = <CALayer: 0x1d872110>> at indexPath #15
    2013-08-17 10:59:49.118 SFCCA[22885:907] <UIProgressView: 0x1d8b9e20; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 12; layer = <CALayer: 0x1d8a6140>> at indexPath #12
    2013-08-17 10:59:49.127 SFCCA[22885:907] <UIProgressView: 0x1d8cc060; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 13; layer = <CALayer: 0x1d8ca870>> at indexPath #13
    2013-08-17 10:59:49.730 SFCCA[22885:907] <UIProgressView: 0x1d8c9aa0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 10; layer = <CALayer: 0x1d8c9480>> at indexPath #10
    2013-08-17 10:59:49.736 SFCCA[22885:907] <UIProgressView: 0x1d8cb590; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 11; layer = <CALayer: 0x1d8cb4b0>> at indexPath #11
    2013-08-17 10:59:50.106 SFCCA[22885:907] <UIProgressView: 0x1d8c3b90; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 8; layer = <CALayer: 0x1d8c3c30>> at indexPath #8
    2013-08-17 10:59:50.113 SFCCA[22885:907] <UIProgressView: 0x1c5e08d0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 9; layer = <CALayer: 0x1c5b9330>> at indexPath #9
    2013-08-17 10:59:50.643 SFCCA[22885:907] <UIProgressView: 0x1c5d5a10; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 6; layer = <CALayer: 0x1c5b4420>> at indexPath #6
    2013-08-17 10:59:50.649 SFCCA[22885:907] <UIProgressView: 0x1c5cd8e0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 7; layer = <CALayer: 0x1c5b68d0>> at indexPath #7
    2013-08-17 10:59:50.967 SFCCA[22885:907] <UIProgressView: 0x1c5aa670; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 4; layer = <CALayer: 0x1c5b8d60>> at indexPath #4
    2013-08-17 10:59:50.973 SFCCA[22885:907] <UIProgressView: 0x1c5b51d0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 5; layer = <CALayer: 0x1c5b5270>> at indexPath #5
    2013-08-17 10:59:51.593 SFCCA[22885:907] <UIProgressView: 0x1c5aa1f0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 2; layer = <CALayer: 0x1c5aa270>> at indexPath #2
    2013-08-17 10:59:51.598 SFCCA[22885:907] <UIProgressView: 0x1c5b9860; frame = (20 248; 150 9); opaque = NO; tag = 3; layer = <CALayer: 0x1c5b9a30>> at indexPath #3
    2013-08-17 10:59:51.983 SFCCA[22885:907] <UIProgressView: 0x1c5bca00; frame = (20 248; 150 9); hidden = YES; opaque = NO; layer = <CALayer: 0x1c5d1000>> at indexPath #0
    2013-08-17 10:59:51.995 SFCCA[22885:907] <UIProgressView: 0x1c59c7c0; frame = (20 248; 150 9); hidden = YES; opaque = NO; tag = 1; layer = <CALayer: 0x1c5bb310>> at indexPath #1
    

3 个答案:

答案 0 :(得分:3)

经过2周的挣扎,管理解决这个问题。简单的解决方案,但我没想到它。

我有一个属性如下@property (strong, nonatomic) NSMutableArray *progressViewsArray;。不要忘记分配和初始化它。我是在viewDidLoad中完成的。

collectionView:cellForItemAtIndexPath:中,我在返回单元格之前使用了以下逻辑。

for (UIProgressView *progressView in cell.contentView.subviews)
{
    if ([progressView isKindOfClass:[UIProgressView class]])
    {
        [progressView removeFromSuperview];
    }
}
for (UIProgressView *progressView in self.progressViewsArray)
{
    if (progressView.tag == indexPath.item)
    {
        [cell.contentView addSubview:progressView];
    }
}

downloadButtonTapped:中,这是我创建UIProgressView实例的方式:

UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
progressView.frame = CGRectMake(178, 180, 170, 9);
[progressView setTag:indexPath.item];
[cell.contentView addSubview:progressView];
[self.progressViewsArray addObject:progressView];

在AFNetworking的setDownloadProgressBlock(downloadButtonTapped:)中:

float progress = (float) totalBytesRead / totalBytesExpectedToRead;
[progressView setProgress:progress];

最后在AFNetworking的setCompletionBlock(downloadButtonTapped:)中:

NSMutableArray *progressViewsToDelete = [[NSMutableArray alloc] init];
for (UIProgressView *pv in self.progressViewsArray)
{
    if (pv.tag == indexPath.item)
    {
        [progressViewsToDelete addObject:pv];
    }
}
if (progressViewsToDelete.count > 0)
{
    [self.progressViewsArray removeObjectsInArray:progressViewsToDelete];
}
[self.collectionView reloadItemsAtIndexPaths:@[indexPath]]; // To reflect changes.

希望这能帮助将来的人,干杯!

答案 1 :(得分:0)

您应该将所有视图添加到原型单元格中,并将其中一些设置为隐藏。但具体来说,在collectionView:cellForItemAtIndexPath:中,您应该设置所配置的所有视图的hidden属性,以便在需要时使其可见,并在不需要时隐藏它们。然后,无论细胞是新的还是重复使用都无关紧要,您始终可以保证正确的视图可见。

在您当前的解决方案中,您有一些逻辑可以阻止创建新的进度视图(如果已有)。但是,您实际上从未从单元格中删除任何进度视图。因此,当您重复使用单元格时,它仍可能具有进度视图作为子视图。使用隐藏视图或显示视图(并设置进度值)的方法可以避免这种情况。

答案 2 :(得分:0)

我有类似的问题。我解决了它。您已在此方法中更改了单元格的子视图:- (IBAction)downloadButtonTapped:(id)sender,并且您未将此子视图更新为方法:collectionView:cellForItemAtIndexPath:。当重用单元格工作时,它只是从这个方法获取视图:collectionView:cellForItemAtIndexPath:,并且不包括在此方法之外更改的子视图,因此您应该在方法collectionView:cellForItemAtIndexPath:中执行某些操作来更新您的更改关于细胞的子视图。无论如何,我希望这可以帮助你。