UIActivityIndi​​catorView在UITableViewCell中停止动画

时间:2015-02-26 08:40:17

标签: ios iphone uiactivityindicatorview

我有一个表视图,在该表视图中,我有一个UIActivityIndi​​cator,每个单元格中都有一个按钮。现在单击该按钮我想启动ActivityIndi​​cator动画,它的开始。但问题是当我滚动表格视图时它会停止动画。这是我的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;
}

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

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

2 个答案:

答案 0 :(得分:67)

我想我可以了解旋转器何时以及如何停止在细胞中旋转。 我已经将UIActivityIndicatorView子类化为我自己的类重载startAnimatingstopAnimating函数并在其中加入断点。我制作了一个简单的单元格,上面只有一个旋转器。我在IB中将微调器的动画属性设置为true: enter image description here

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

在我看来,这是在细胞创建流程中发生的,所以首先它没有动画进行初始化,然后IB设置启动并启动动画。当旋转器停止动画时,现在这里是有趣的部分: enter image description here

看起来,当细胞从屏幕上移除时,微调器一直在旋转,当细胞准备通过私有函数prepareForReuse再次显示在屏幕上时(_removeAllAnimations)停止旋转。似乎递归迭代所有子视图。 问题在于,出于某种原因,UIKit的私有函数从不重新启用动画,startAnimating永远不会被调用。实际上IMO禁用动画是真正的问题。

我提出的解决方案,并且它并不完美,但它显然是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

答案 1 :(得分: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"];
}