ios UIActivityIndicatorView未在UICollectionViewCell中旋转

7gs2gvoe  于 2023-05-19  发布在  iOS
关注(0)|答案(5)|浏览(149)

我有一个自定义单元格,它加载在集合视图的底部。它唯一的工作是显示一个活动指示器视图-这在应用程序进行新的工作呼叫时发生。
所以我把它添加到单元格中,就像这样:

BBLoaderCell *loaderCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"LoaderCell" forIndexPath:indexPath];

UIActivityIndicatorView * activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.hidden = NO;
activityIndicator.center = loaderCell.imageView.center;
activityIndicator.tag = 10;

[loaderCell.imageView addSubview:activityIndicator];

    [activityIndicator startAnimating];
    return loaderCell;

这在我的视图的最后一个单元格中显示了一个活动指示器-但是它不旋转。有什么想法吗

找到解决方案

根据评论-这是一个线程问题。我还采纳了将代码移到单元格的自定义nib文件的建议。
下面是重构后的代码:

BBLoaderCell *loaderCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"LoaderCell" forIndexPath:indexPath];
    loaderCell.backgroundColor = [UIColor clearColor];

     if (self.loadingMore == NO){
        dispatch_async(dispatch_get_main_queue(), ^{
            activityIndicator.hidden = YES;
            [loaderCell.spinner stopAnimating];
        });
    }
     else if (self.loadingMore == YES){
    dispatch_async(dispatch_get_main_queue(), ^{
        activityIndicator.hidden = NO;
        [loaderCell.spinner startAnimating];
    });
    }

    return loaderCell;

这是我需要的工作。
谢谢你们!

olhwl3o2

olhwl3o21#

您很可能在很短的时间内多次调用reloadData。也许已经在下一帧了。默认情况下,活动指示器在停止时隐藏。这是发生了什么:
1.首先reloadData显示微调器
1.第二次reloadData也会重新加载单元格,微调器会隐藏自己
1.现在微调器被隐藏了
1.你滚动但是单元格被重复使用了。微调器还藏着
您可以设置activityIndicator.hidesWhenStopped = false。微调器现在应该始终可见。但它不转。
添加此选项将恢复旋转。

override func prepareForReuse() {
   activityIndicator.startAnimating()
}

另一个问题可能是颜色。也许微调器的颜色与背景相同。尝试像这样设置微调器的颜色:

activityIndicator.color = .red

您可以使用“Debug View Hierarchy(调试视图层次结构)”按钮

检查微调器是否在那里
它将显示当前可见屏幕

的线框

8cdiaqws

8cdiaqws2#

我认为这可能与线程有关(例如。主线程上的UI未准备好使指示器动画化)。您可以尝试以下操作:
[activityIndicator performSelector:@selector(startAnimating:) withObject:nil afterDelay:1];
这只是一个可能的建议,但你应该尝试不同的变化,并检查哪一个强制动画到主线程正确和及时的问题。另一种变化:

dispatch_async(dispatch_get_main_queue(), ^{
    [activityIndicator startAnimating];
});
aor9mmx1

aor9mmx13#

一个更简洁的解决方案是在willDisplay委托方法中启动动画:

public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  (cell as? BBLoaderCell)?.activityIndicatorView.startAnimating()
}

由于在iOS 10或更高版本上,默认情况下启用预取,因此即使单元格多次滚动进出屏幕,也可能只有1次cellForItemAt调用。当单元格滚动出屏幕时,似乎调用了stopAnimating()isAnimating也变为false)。因此在cellForItemAt内部使用异步延迟可能会在单元格第二次进入屏幕后失败。在iOS11上依然如此
由于每当单元格进入屏幕时都会调用willDisplay,因此我们可以在那里可靠地重新开始动画

waxmsbnn

waxmsbnn4#

在我的例子中,我在customCell上使用activityIndicator作为tableView,我遇到了同样的问题,即使在写下activityIndicator.startAnimating()之后,加载也没有移动。
经过几个小时的尝试,我想出了一个解决方案。

override func prepareForReuse() {
       activityIndicator.startAnimating()
}

当您重用activityIndicator正在动画化的customCell时,只需使用方法prepareForReuse()show

ngynwnxp

ngynwnxp5#

如果子类化你的UIActivityIndicatorView并在stopAnimation方法中放置一个断点,你可以看到在单元格出队时调用了一个私有方法来删除所有的动画。这将导致指示器隐藏或停止(如果hidesWhenStopped设置为false)。

相关问题