チタンデコイのリクエストで、この問題を修正した方法は次のとおりです。
1 秒に 1 回実行されるを持つUIViewController
サブクラスがあり、基になるデータ ソースでの呼び出しが必要であることを示す変更がないNSTimer
かチェックします。そのため、そのサブクラスに次を追加しました。UITableView
-reloadData
@property (BOOL) IsAnimating;
これを最初に に設定しNO
、isAnimating
プロパティが に設定されているYES
場合、NSTimer
「短絡」して通常の処理をスキップします。
したがって、このアニメーションを実行する場合は、プロパティをUITableView
に設定してアニメーションを実行します。isAnimating
YES
次に、セレクターを 1 秒後に実行するようにスケジュールします。これは にリセットさisAnimating
れNO
ます。はNSTimer
その後も発火を続け、isAnimating
ofを確認しNO
(おそらく の 2 回目の呼び出しで-codeTimerFired
)、データ ソースの更新を見つけて への呼び出しを開始しreloadData
ます。
の処理を中断し、アニメーションNSTimer
をスケジュールするコードは次のとおりです。UITableView
// currentIndex and newIndex have already been calculated as the data item's
// original and destination indices (only 1 section in UITableView)
if (currentIndex != newIndex) {
// This item's index has changed, so animate its movement
NSIndexPath *oldPath = [NSIndexPath indexPathForRow:currentIndex inSection:0];
NSIndexPath *newPath = [NSIndexPath indexPathForRow:newIndex inSection:0];
// Set a flag to disable data source processing and calls to [UITableView reloadData]
[[self Owner] setIsAnimating:YES];
// I haven't tested enough, but some documentation leads me to believe
// that this particular call (-moveRowAtIndexPath:toIndexPath:) may NOT need
// to be wrapped in a -beginUpdates/-endUpdates block
[[[self Owner] InstructionsTableView] beginUpdates];
// These lines move the item in my data source
[[[MMAppDelegate singleton] CurrentChecklist] removeObject:[self CellTask]];
[[[MMAppDelegate singleton] CurrentChecklist] insertObject:[self CellTask] atIndex:newIndex];
// This code is the UITableView animation
[[[self Owner] InstructionsTableView] moveRowAtIndexPath:oldPath toIndexPath:newPath];
// Conclude the UITableView animation block
[[[self Owner] InstructionsTableView] endUpdates];
// Schedule a call to re-enable UITableView animation
[[self Owner] performSelector:@selector(setIsAnimating:) withObject:@(NO) afterDelay:1.0];
} else {
// This location hasn't changed, so just tell my owner to reload its data
[[[self Owner] InstructionsTableView] reloadData];
}
メソッドは次のとおりNSTimer
です( の場合にどのように救済されるかに注意してくださいisAnimating == YES
):
- (void)codeTimerFired {
// This is a subclass of a template subclass...
// super actually has work to do in this method...
[super codeTimerFired];
// If we're in the middle of an animation, don't update!
if ([self IsAnimating]) {
return;
}
// Other data source processing...
// local BOOL to check whether underlying data source has changed
BOOL shouldUpdate = NO;
// code to check if underlying data source has changed...
// ******************************************************
// [CODE REMOVED]
// ******************************************************
// If the underlying data source has changed, update the UITableView
if (shouldUpdate) {
[self reloadTableView]; // <--- This is the main line I wanted to prevent
// since the code that fired to cause the
// UITableView animation will ALWAYS cause
// the underlying data source to change such
// that this line would fire.
}
}