web-dev-qa-db-ja.com

UIActivityIndi​​catorViewはUITableViewCellでのアニメーションを停止します

1つのテーブルビューがあり、そのテーブルビューには、すべてのセルに1つのボタンがあるUIActivityIndi​​catorが1つあります。次に、そのボタンをクリックして、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];
}
27
Rakesh

スピナーがセル内で回転を停止するタイミングと方法に光を当てることができると思います。 UIActivityIndicatorViewをサブクラス化して自分のクラスでstartAnimating関数とstopAnimating関数をオーバーロードし、ブレークポイントを設定しました。クラスのスピナーだけを使って単純なセルを作成しました。 IBでスピナーのAnimatingプロパティをtrueに設定しました: enter image description here

これが何が起こるかです。最初の2つのスクリーンショットには、同じプライベート関数_didMoveFromWindow:toWindowで2つのアクション(アニメーションの停止と開始)が次々に発生していることを示すスタックトレースがあります。 enter image description hereenter image description here

これはセル作成フローで発生しているように思われるため、最初にアニメーションなしで初期化され、次にIB設定が開始されてアニメーションが開始されます。スピナーがアニメーションを停止したときの興味深い部分は次のとおりです。 enter image description here

したがって、セルが画面から削除されるとスピナーは回転し続け、セルがプライベート関数_removeAllAnimationsを介して画面に再び表示される準備ができると停止するようです(prepareForReuse)。すべての子ビューを再帰的に繰り返します。問題は、何らかの理由で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
68
user3099609

スクロール時に新しい表示セルを順番にロードするときに、どのセルのアクティビティインジケータがtableViewとして開始されたかを維持する必要があります。その結果、アクティビティインジケータが停止します。

メンバーオブジェクトをクラス化するアクティビティインジケーターステータスに1つの配列を使用します。

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"];
}
4
Paresh Navadiya