UITableViewCell 中的 UIActivityIndicatorView 停止动画

36

我有一个表格视图,在其中有一个UIActivityIndicator和一个按钮,每个单元格中都有一个。现在当点击该按钮时,我想要开始ActivityIndicator的动画,它已经开始了。但问题是当我滚动表格视图时,它停止了动画。这是我的cellForRowAtIndexPath的代码:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"txDevicesListCellID"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"txDevicesListCellID"];
    }
    UIButton *buttonutton = (UIButton *)[cell viewWithTag:103];
    UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *) [cell viewWithTag:104];
    button.tag = indexPath.row;
    return cell;
}

我的按钮的 and 选择器方法是

-(IBAction)recevierButtonClick:(id)sender{
    UIButton *button = (UIButton *)sender;
    NSInteger index = button.tag;
    NSIndexPath* indexpath = [NSIndexPath indexPathForRow:serialNumber inSection:0];
    UITableViewCell* cell = [self.myTableView cellForRowAtIndexPath:indexpath];
    activityIndicator = (UIActivityIndicatorView*)[cell viewWithTag:index];
    [activityIndicator startAnimating];
}

如果(cell == nil){ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"txDevicesListCellID"]; UIButton *button = (UIButton *)[cell viewWithTag:103]; UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *) [cell viewWithTag:104]; }button.tag = indexPath.row; 尝试这个。因为活动指示器被重新初始化,所以没有动画。 - RJV Kumar
2个回答

93

我想我可以解释一下细胞中旋转器何时以及如何停止旋转。

我使用自己的类重载了startAnimatingstopAnimating函数,并在其中设置断点,对UIActivityIndicatorView进行子类化。 我制作了一个只包含自己类的旋转器的简单单元格。我在IB中将旋转器的“Animating”属性设置为true:

enter image description here

现在看看发生了什么。前两个屏幕截图显示了堆栈跟踪,指示两个操作(停止动画和启动动画)一个接一个地在同一私有函数_didMoveFromWindow:toWindow中发生:

enter image description hereenter image description here

在我看来,这是在单元格创建流程中发生的,因此首先不带动画初始化,然后IB设置会启动动画。 现在有趣的部分是,当旋转器停止旋转时:

enter image description here

因此看起来细胞从屏幕中移除时旋转器仍在旋转,并且在为再次显示在屏幕上做准备的单元格(prepareForReuse)中通过私有函数_removeAllAnimations停止。它似乎递归地迭代所有子视图。

问题在于由于某种原因UIKit的私有函数从未重新启用动画,startAnimating也从未被调用。 实际上我认为禁用动画才是真正的问题。

我提出的解决方案并不完美,但显然这是Apple希望我们采取的措施,即对包含旋转器的单元格进行UITableViewCell子类化,并在prepareForReuse中重新启用它们:

class SpinnerCell: UITableViewCell {
    @IBOutlet weak var spinner: UIActivityIndicatorView?

    override func prepareForReuse() {
        super.prepareForReuse()
        if let spinner = self.spinner {
            spinner.startAnimating()
        }
    }
}

或者在 Obj-C 中:

@interface SpinnerCell

@property (weak) IBOutlet UIActivityIndicatorView *spinner;

@end

@implementation SpinnerCell

- (void)prepareForReuse {
    [super prepareForReuse];
    [self.spinner startAnimating];
}

@end

2
OFM是这种情况的完美前缀。 - hfossli
我们在弗朗西斯科会喜欢我们的 Obj-C 前缀。 - user3099609
太有趣了!我希望你是在开玩笑。如果不是,我希望这不会冒犯到你。但对于那些不熟悉方济各会的人来说,他们可能会想到http://www.urbandictionary.com/define.php?term=ofm&defid=3084325,而不是最小修士会(O.F.M.)。 - hfossli
3
好的回答。值得获得最佳答案标记。 - Dirty Henry
1
由于Spinner是可选的,因此可以使用spinner?.startAnimating()来省略if let spinner = self.spinner - Pim
@Pim:没错。那时候我不太擅长Swift ^_^ - user3099609

4
您需要维护tableView滚动时已经开始的单元格活动指示器,以便按顺序加载新的可见单元格。这样可以停止活动指示器。
使用一个数组来表示活动指示器状态,并将其作为类成员对象。
NSMutableArray *mutArrActIndStatus;

//Intialization
mutArrActIndStatus = [NSMutableArray array];

现在将对象添加到tableView数据源中。注意1表示开始,0表示停止。因此最初所有内容都处于停止状态。
for(int i=0; i<[yourTableViewArray count]; i++)
{
    [mutArrActIndStatus addObject:@"0"];
}

现在在您的tableView中使用它:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   //...............
   //................

   UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *) [cell viewWithTag:104];
   button.tag = indexPath.row;

   NSString *strActIndStatus = mutArrActIndStatus[indexPath.row];
   if([strActIndStatus isEqualToString:@"1"])
   {
      [activityIndicator startAnimating];
   }

   return cell;
}

下一步,在按钮方法中进行更改,以替换活动指示器的状态。
-(IBAction)recevierButtonClick:(id)sender{

   //for find index here to replace status of activity indicator
   UIButton *btnSender = (UIButton *)sender;
   [mutArrActIndStatus replaceObjectAtIndex:btnSender.tag withObject:@"1"];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接