From 1530ef2841b71b56f377d822bbba280d16631098 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Thu, 7 May 2015 21:53:38 -0700 Subject: [PATCH 1/2] Prevent UITableView insertion/deletion animations by default Fixes #292 --- AsyncDisplayKit/ASCollectionView.mm | 2 +- AsyncDisplayKit/ASTableView.mm | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 04200238bf..0583ae3b28 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -15,7 +15,7 @@ #import "ASDisplayNodeInternal.h" #import "ASBatchFetching.h" -const static NSUInteger kASCollectionViewAnimationNone = 0; +const static NSUInteger kASCollectionViewAnimationNone = UITableViewRowAnimationNone; #pragma mark - diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index ff2410eab0..02a5ced3fe 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -126,6 +126,16 @@ static BOOL _isInterceptedSelector(SEL sel) @implementation ASTableView +void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { + if (withoutAnimation) { + [UIView setAnimationsEnabled:NO]; + block(); + [UIView setAnimationsEnabled:YES]; + } else { + block(); + } +} + #pragma mark - #pragma mark Lifecycle @@ -467,29 +477,36 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { ASDisplayNodeAssertMainThread(); - - [super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + [super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + }); } - (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { ASDisplayNodeAssertMainThread(); - [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + }); } - (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { ASDisplayNodeAssertMainThread(); - [super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + [super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + }); } - (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { ASDisplayNodeAssertMainThread(); - [super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + [super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + }); } #pragma mark - ASDataControllerDelegate From c8ea73b1fedf58134b7f16642c0ec6169599b934 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Mon, 18 May 2015 20:03:14 -0700 Subject: [PATCH 2/2] Communicate conditionals clearly and document methods --- AsyncDisplayKit/ASTableView.mm | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 02a5ced3fe..0e35b03e2d 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -126,11 +126,21 @@ static BOOL _isInterceptedSelector(SEL sel) @implementation ASTableView +/** + @summary Conditionally performs UIView geometry changes in the given block without animation. + + Used primarily to circumvent UITableView forcing insertion animations when explicitly told not to via + `UITableViewRowAnimationNone`. More info: https://github.com/facebook/AsyncDisplayKit/pull/445 + + @param withoutAnimation Set to `YES` to perform given block without animation + @param block Perform UIView geometry changes within the passed block + */ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { if (withoutAnimation) { + BOOL animationsEnabled = [UIView areAnimationsEnabled]; [UIView setAnimationsEnabled:NO]; block(); - [UIView setAnimationsEnabled:YES]; + [UIView setAnimationsEnabled:animationsEnabled]; } else { block(); } @@ -477,7 +487,9 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { - (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { ASDisplayNodeAssertMainThread(); - ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + + BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + ASPerformBlockWithoutAnimation(preventAnimation, ^{ [super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; }); } @@ -486,7 +498,8 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { { ASDisplayNodeAssertMainThread(); - ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + ASPerformBlockWithoutAnimation(preventAnimation, ^{ [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; }); } @@ -495,7 +508,8 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { { ASDisplayNodeAssertMainThread(); - ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + ASPerformBlockWithoutAnimation(preventAnimation, ^{ [super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; }); } @@ -504,7 +518,8 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { { ASDisplayNodeAssertMainThread(); - ASPerformBlockWithoutAnimation(animationOption == UITableViewRowAnimationNone, ^{ + BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + ASPerformBlockWithoutAnimation(preventAnimation, ^{ [super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; }); }