2

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

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

    • UIButton (action:@selector(downloadButtonTapped:))

    和一个

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

我有 22 个对象的数据源,因此,我有 22 个单元格。到目前为止,一切都像我想要的那样工作。即使我将单元格滚动出视图(出队)并返回视图(回收), UIProgressView 仍然存在。

问题:

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

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

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

PS 下面编辑调试尝试。


以下是涉及的方法:

集合视图: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;
}

下载ButtonTapped:

- (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 的下载按钮滚动到底部返回到collectionView 的顶部,像往常一样看到单元格 10 和 19 的进度视图也处于活动状态,这就是我记录的内容。如您所见,当下载处于活动状态时,日志显示只有单元格 3 的 progressView (tag=3) 为 ( setHidden=NO )。单元格 10 和 19 仍然隐藏/不受影响。但我不明白为什么我在那里看到一个活跃的progressView。

这是日志:

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
4

3 回答 3

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.

希望这对将来的人有所帮助,干杯!

于 2013-08-21T08:18:08.920 回答
0

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

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

于 2013-08-16T15:29:57.407 回答
0

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

于 2013-08-18T12:00:01.097 回答