Revert "ASDataController now handles reloadData more efficiently and notify its delegate once instead of a series of deletes and inserts"

This reverts commit 2e4d716e0b.

Possible issue with this commit.
This commit is contained in:
Scott Goodson
2016-01-22 20:33:33 -08:00
parent cb5e5704e2
commit 83aaa4637e
8 changed files with 36 additions and 179 deletions

View File

@@ -250,7 +250,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
_superIsPendingDataLoad = YES; _superIsPendingDataLoad = YES;
[super reloadData]; [super reloadData];
}); });
[_dataController reloadDataWithCompletion:completion]; [_dataController reloadDataWithAnimationOptions:kASCollectionViewAnimationNone completion:completion];
} }
- (void)reloadData - (void)reloadData
@@ -262,7 +262,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
{ {
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
_superIsPendingDataLoad = YES; _superIsPendingDataLoad = YES;
[_dataController reloadDataImmediately]; [_dataController reloadDataImmediatelyWithAnimationOptions:kASCollectionViewAnimationNone];
[super reloadData]; [super reloadData];
} }
@@ -938,25 +938,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
} }
} }
- (void)rangeControllerDidReloadData:(ASRangeController *)rangeController
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
if (_performingBatchUpdates) {
[_batchUpdateBlocks addObject:^{
[super reloadData];
}];
} else {
[UIView performWithoutAnimation:^{
[super reloadData];
}];
}
}
#pragma mark - ASCellNodeDelegate #pragma mark - ASCellNodeDelegate
- (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged - (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged

View File

@@ -298,7 +298,10 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
- (void)reloadDataWithCompletion:(void (^)())completion - (void)reloadDataWithCompletion:(void (^)())completion
{ {
[_dataController reloadDataWithCompletion:completion]; ASPerformBlockOnMainThread(^{
[super reloadData];
});
[_dataController reloadDataWithAnimationOptions:UITableViewRowAnimationNone completion:completion];
} }
- (void)reloadData - (void)reloadData
@@ -309,7 +312,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
- (void)reloadDataImmediately - (void)reloadDataImmediately
{ {
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
[_dataController reloadDataImmediately]; [_dataController reloadDataImmediatelyWithAnimationOptions:UITableViewRowAnimationNone];
[super reloadData];
} }
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
@@ -841,18 +845,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
}); });
} }
- (void)rangeControllerDidReloadData:(ASRangeController *)rangeController
{
ASDisplayNodeAssertMainThread();
LOG(@"UITableView reloadData");
if (!self.asyncDataSource) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
[super reloadData];
}
#pragma mark - ASDataControllerDelegate #pragma mark - ASDataControllerDelegate
- (ASCellNode *)dataController:(ASDataController *)dataController nodeAtIndexPath:(NSIndexPath *)indexPath - (ASCellNode *)dataController:(ASDataController *)dataController nodeAtIndexPath:(NSIndexPath *)indexPath

View File

@@ -55,7 +55,7 @@
- (void)willReloadData - (void)willReloadData
{ {
[_pendingNodes enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray *nodes, BOOL *stop) { [_pendingNodes enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray *nodes, BOOL *stop) {
// Remove everything that existed before the reload, now that we're ready to insert replacements // Remove everything that existed before the reload, now that we're ready to insert replacements
NSArray *indexPaths = [self indexPathsForEditingNodesOfKind:kind]; NSArray *indexPaths = [self indexPathsForEditingNodesOfKind:kind];
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; [self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];

View File

@@ -94,11 +94,6 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
*/ */
- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; - (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/**
Called for data reload.
*/
- (void)dataControllerDidReloadData:(ASDataController *)dataController;
@end @end
/** /**
@@ -175,9 +170,9 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
- (void)reloadDataWithCompletion:(void (^ _Nullable)())completion; - (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^ _Nullable)())completion;
- (void)reloadDataImmediately; - (void)reloadDataImmediatelyWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/** @name Data Querying */ /** @name Data Querying */

View File

@@ -43,7 +43,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
BOOL _delegateDidDeleteNodes; BOOL _delegateDidDeleteNodes;
BOOL _delegateDidInsertSections; BOOL _delegateDidInsertSections;
BOOL _delegateDidDeleteSections; BOOL _delegateDidDeleteSections;
BOOL _delegateDidReloadData;
} }
@property (atomic, assign) NSUInteger batchUpdateCounter; @property (atomic, assign) NSUInteger batchUpdateCounter;
@@ -93,7 +92,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
_delegateDidDeleteNodes = [_delegate respondsToSelector:@selector(dataController:didDeleteNodes:atIndexPaths:withAnimationOptions:)]; _delegateDidDeleteNodes = [_delegate respondsToSelector:@selector(dataController:didDeleteNodes:atIndexPaths:withAnimationOptions:)];
_delegateDidInsertSections = [_delegate respondsToSelector:@selector(dataController:didInsertSections:atIndexSet:withAnimationOptions:)]; _delegateDidInsertSections = [_delegate respondsToSelector:@selector(dataController:didInsertSections:atIndexSet:withAnimationOptions:)];
_delegateDidDeleteSections = [_delegate respondsToSelector:@selector(dataController:didDeleteSectionsAtIndexSet:withAnimationOptions:)]; _delegateDidDeleteSections = [_delegate respondsToSelector:@selector(dataController:didDeleteSectionsAtIndexSet:withAnimationOptions:)];
_delegateDidReloadData = [_delegate respondsToSelector:@selector(dataControllerDidReloadData:)];
} }
+ (NSUInteger)parallelProcessorCount + (NSUInteger)parallelProcessorCount
@@ -145,30 +143,14 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height); node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height);
} }
/**
* Measures and defines the layout for each node in optimized batches on an editing queue, inserting the results into the backing store.
*/
- (void)_batchLayoutNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths
{
[self _batchLayoutNodes:nodes atIndexPaths:indexPaths andNotifyDelegate:NO withAnimationOptions:0];
}
/** /**
* Measures and defines the layout for each node in optimized batches on an editing queue, inserting the results into the backing store. * Measures and defines the layout for each node in optimized batches on an editing queue, inserting the results into the backing store.
*/ */
- (void)_batchLayoutNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions - (void)_batchLayoutNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
[self _batchLayoutNodes:nodes atIndexPaths:indexPaths andNotifyDelegate:YES withAnimationOptions:animationOptions];
}
/**
* Measures and defines the layout for each node in optimized batches on an editing queue, inserting the results into the backing store.
*/
- (void)_batchLayoutNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths andNotifyDelegate:(BOOL)shouldNotifyDelegate withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{ {
[self batchLayoutNodes:nodes ofKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:^(NSArray *nodes, NSArray *indexPaths) { [self batchLayoutNodes:nodes ofKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:^(NSArray *nodes, NSArray *indexPaths) {
// Insert finished nodes into data storage // Insert finished nodes into data storage
[self _insertNodes:nodes atIndexPaths:indexPaths andNotifyDelegate:shouldNotifyDelegate withAnimationOptions:animationOptions]; [self _insertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions];
}]; }];
} }
@@ -258,14 +240,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
}]; }];
} }
- (void)deleteAllNodesOfKind:(NSString *)kind
{
[_editingNodes[kind] removeAllObjects];
[_mainSerialQueue performBlockOnMainThread:^{
[_completedNodes[kind] removeAllObjects];
}];
}
- (void)insertSections:(NSMutableArray *)sections ofKind:(NSString *)kind atIndexSet:(NSIndexSet *)indexSet completion:(void (^)(NSArray *sections, NSIndexSet *indexSet))completionBlock - (void)insertSections:(NSMutableArray *)sections ofKind:(NSString *)kind atIndexSet:(NSIndexSet *)indexSet completion:(void (^)(NSArray *sections, NSIndexSet *indexSet))completionBlock
{ {
if (indexSet.count == 0) if (indexSet.count == 0)
@@ -303,17 +277,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
#pragma mark - Internal Data Querying + Editing #pragma mark - Internal Data Querying + Editing
/**
* Inserts the specified nodes into the given index paths and doesn't notify the delegate of newly inserted nodes.
*
* @discussion Nodes are first inserted into the editing store, then the completed store is replaced by a deep copy
* of the editing nodes.
*/
- (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths
{
[self _insertNodes:nodes atIndexPaths:indexPaths andNotifyDelegate:NO withAnimationOptions:0];
}
/** /**
* Inserts the specified nodes into the given index paths and notifies the delegate of newly inserted nodes. * Inserts the specified nodes into the given index paths and notifies the delegate of newly inserted nodes.
* *
@@ -322,26 +285,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
*/ */
- (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions - (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{ {
[self _insertNodes:nodes atIndexPaths:indexPaths andNotifyDelegate:YES withAnimationOptions:animationOptions]; [self insertNodes:nodes ofKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:^(NSArray *nodes, NSArray *indexPaths) {
} if (_delegateDidInsertNodes)
[_delegate dataController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions];
/** }];
* Inserts the specified nodes into the given index paths and notifies the delegate of newly inserted nodes.
*
* @discussion Nodes are first inserted into the editing store, then the completed store is replaced by a deep copy
* of the editing nodes. The delegate is invoked on the main thread.
*/
- (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths andNotifyDelegate:(BOOL)shouldNotifyDelegate withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
void (^completionBlock)(NSArray *nodes, NSArray *indexPaths) = nil;
if (shouldNotifyDelegate) {
completionBlock = ^(NSArray *nodes, NSArray *indexPaths) {
if (_delegateDidInsertNodes)
[_delegate dataController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions];
};
}
[self insertNodes:nodes ofKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:completionBlock];
} }
/** /**
@@ -358,46 +305,18 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
}]; }];
} }
/**
* Inserts sections, represented as arrays, into the backing store at the given indicies and doesn't notify the delegate.
*
* @discussion The section arrays are inserted into the editing store, then a deep copy of the sections are inserted
* in the completed store on the main thread.
*/
- (void)_insertSections:(NSMutableArray *)sections atIndexSet:(NSIndexSet *)indexSet
{
[self _insertSections:sections atIndexSet:indexSet andNotifyDelegate:NO withAnimationOptions:0];
}
/**
* Inserts sections, represented as arrays, into the backing store at the given indicies and doesn't notify the delegate.
*
* @discussion The section arrays are inserted into the editing store, then a deep copy of the sections are inserted
* in the completed store on the main thread.
*/
- (void)_insertSections:(NSMutableArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
[self _insertSections:sections atIndexSet:indexSet andNotifyDelegate:YES withAnimationOptions:animationOptions];
}
/** /**
* Inserts sections, represented as arrays, into the backing store at the given indicies and notifies the delegate. * Inserts sections, represented as arrays, into the backing store at the given indicies and notifies the delegate.
* *
* @discussion The section arrays are inserted into the editing store, then a deep copy of the sections are inserted * @discussion The section arrays are inserted into the editing store, then a deep copy of the sections are inserted
* in the completed store on the main thread. The delegate is invoked on the main thread. * in the completed store on the main thread. The delegate is invoked on the main thread.
*/ */
- (void)_insertSections:(NSMutableArray *)sections atIndexSet:(NSIndexSet *)indexSet andNotifyDelegate:(BOOL)shouldNotifyDelegate withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions - (void)_insertSections:(NSMutableArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{ {
[self insertSections:sections ofKind:ASDataControllerRowNodeKind atIndexSet:indexSet completion:^(NSArray *sections, NSIndexSet *indexSet) {
void (^completionBlock)(NSArray *sections, NSIndexSet *indexSet) = nil; if (_delegateDidInsertSections)
if (shouldNotifyDelegate) { [_delegate dataController:self didInsertSections:sections atIndexSet:indexSet withAnimationOptions:animationOptions];
completionBlock = ^(NSArray *sections, NSIndexSet *indexSet) { }];
if (_delegateDidInsertSections)
[_delegate dataController:self didInsertSections:sections atIndexSet:indexSet withAnimationOptions:animationOptions];
};
}
[self insertSections:sections ofKind:ASDataControllerRowNodeKind atIndexSet:indexSet completion:completionBlock];
} }
/** /**
@@ -442,17 +361,17 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
}]; }];
} }
- (void)reloadDataWithCompletion:(void (^)())completion - (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^)())completion
{ {
[self _reloadDataSynchronously:NO completion:completion]; [self _reloadDataWithAnimationOptions:animationOptions synchronously:NO completion:completion];
} }
- (void)reloadDataImmediately - (void)reloadDataImmediatelyWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{ {
[self _reloadDataSynchronously:YES completion:nil]; [self _reloadDataWithAnimationOptions:animationOptions synchronously:YES completion:nil];
} }
- (void)_reloadDataSynchronously:(BOOL)synchronously completion:(void (^)())completion - (void)_reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions synchronously:(BOOL)synchronously completion:(void (^)())completion
{ {
[self performEditCommandWithBlock:^{ [self performEditCommandWithBlock:^{
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
@@ -474,7 +393,12 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
LOG(@"Edit Transaction - reloadData"); LOG(@"Edit Transaction - reloadData");
// Remove everything that existed before the reload, now that we're ready to insert replacements // Remove everything that existed before the reload, now that we're ready to insert replacements
[self deleteAllNodesOfKind:ASDataControllerRowNodeKind]; NSArray *indexPaths = ASIndexPathsForMultidimensionalArray(_editingNodes[ASDataControllerRowNodeKind]);
[self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
NSMutableArray *editingNodes = _editingNodes[ASDataControllerRowNodeKind];
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, editingNodes.count)];
[self _deleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions];
[self willReloadData]; [self willReloadData];
@@ -484,19 +408,12 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
[sections addObject:[[NSMutableArray alloc] init]]; [sections addObject:[[NSMutableArray alloc] init]];
} }
[self _insertSections:sections atIndexSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)]]; [self _insertSections:sections atIndexSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)] withAnimationOptions:animationOptions];
[self _batchLayoutNodes:updatedNodes atIndexPaths:updatedIndexPaths]; [self _batchLayoutNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOptions];
if (_delegateDidReloadData || completion) { if (completion) {
[_mainSerialQueue performBlockOnMainThread:^{ dispatch_async(dispatch_get_main_queue(), completion);
if (_delegateDidReloadData) {
[_delegate dataControllerDidReloadData:self];
}
if (completion) {
completion();
}
}];
} }
}; };

View File

@@ -190,13 +190,6 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; - (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/**
* Called for data reload.
*
* @param rangeController Sender.
*/
- (void)rangeControllerDidReloadData:(ASRangeController *)rangeController;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -276,17 +276,4 @@
}); });
} }
- (void)dataControllerDidReloadData:(ASDataController *)dataController
{
ASPerformBlockOnMainThread(^{
_rangeIsValid = NO;
// When reload data we need to make sure that _rangeTypeIndexPaths is cleared as well,
// otherwise _updateVisibleNodeIndexPaths may try to retrieve nodes from dataSource that aren't there anymore
[_rangeTypeIndexPaths removeAllObjects];
[_delegate rangeControllerDidReloadData:self];
});
}
@end @end

View File

@@ -267,12 +267,4 @@
}); });
} }
- (void)dataControllerDidReloadData:(ASDataController *)dataController
{
ASPerformBlockOnMainThread(^{
_rangeIsValid = NO;
[_delegate rangeControllerDidReloadData:self];
});
}
@end @end