1つのテーブルビューがあり、そのテーブルビューには、すべてのセルに1つのボタンがあるUIActivityIndicatorが1つあります。次に、そのボタンをクリックして、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;
}
私のボタンのセレクターメソッドは
-(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];
}
スピナーがセル内で回転を停止するタイミングと方法に光を当てることができると思います。 UIActivityIndicatorView
をサブクラス化して自分のクラスでstartAnimating
関数とstopAnimating
関数をオーバーロードし、ブレークポイントを設定しました。クラスのスピナーだけを使って単純なセルを作成しました。 IBでスピナーのAnimatingプロパティをtrueに設定しました:
これが何が起こるかです。最初の2つのスクリーンショットには、同じプライベート関数_didMoveFromWindow:toWindow
で2つのアクション(アニメーションの停止と開始)が次々に発生していることを示すスタックトレースがあります。
これはセル作成フローで発生しているように思われるため、最初にアニメーションなしで初期化され、次にIB設定が開始されてアニメーションが開始されます。スピナーがアニメーションを停止したときの興味深い部分は次のとおりです。
したがって、セルが画面から削除されるとスピナーは回転し続け、セルがプライベート関数_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
スクロール時に新しい表示セルを順番にロードするときに、どのセルのアクティビティインジケータが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"];
}