[ASDataController] Simplify data controller (#2923)

* Start removing ASChangeSetDataController

* Continue removing ASChangeSetDataController

* Remove unnecessary change

* ASDataController is no longer an abstract class, remove its assertion

* Get back beginUpdates and endUpdatesAnimated:completion in ASCollectionNode
This commit is contained in:
Huy Nguyen
2017-01-24 17:41:19 -08:00
committed by Adlai Holler
parent 70c48ba906
commit 38f1efd448
16 changed files with 257 additions and 345 deletions

View File

@@ -26,6 +26,7 @@
#import "ASCollectionViewLayoutFacilitatorProtocol.h"
#import "ASSectionContext.h"
#import "ASCollectionView+Undeprecated.h"
#import "_ASHierarchyChangeSet.h"
/**
* A macro to get self.collectionNode and assign it to a local variable, or return
@@ -196,7 +197,17 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
* (0 sections) we always check at least once after each update (initial reload is the first update.)
*/
BOOL _hasEverCheckedForBatchFetchingDueToUpdate;
/**
* The change set that we're currently building, if any.
*/
_ASHierarchyChangeSet *_changeSet;
/**
* Counter used to keep track of nested batch updates.
*/
NSInteger _batchUpdateCount;
struct {
unsigned int scrollViewDidScroll:1;
unsigned int scrollViewWillBeginDragging:1;
@@ -352,6 +363,8 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
- (void)dealloc
{
ASDisplayNodeAssertMainThread();
ASDisplayNodeCAssert(_batchUpdateCount == 0, @"ASCollectionView deallocated in the middle of a batch update.");
// Sometimes the UIKit classes can call back to their delegate even during deallocation, due to animation completion blocks etc.
_isDeallocating = YES;
[self setAsyncDelegate:nil];
@@ -402,6 +415,12 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
- (void)waitUntilAllUpdatesAreCommitted
{
ASDisplayNodeAssertMainThread();
if (_batchUpdateCount > 0) {
// This assertion will be enabled soon.
// ASDisplayNodeFailAssert(@"Should not call %@ during batch update", NSStringFromSelector(_cmd));
return;
}
[_dataController waitUntilAllUpdatesAreCommitted];
}
@@ -761,15 +780,43 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
return _dataController;
}
- (void)beginUpdates
{
ASDisplayNodeAssertMainThread();
// _changeSet must be available during batch update
ASDisplayNodeAssertTrue((_batchUpdateCount > 0) == (_changeSet != nil));
if (_batchUpdateCount == 0) {
_changeSet = [[_ASHierarchyChangeSet alloc] initWithOldData:[_dataController itemCountsFromDataSource]];
}
_batchUpdateCount++;
}
- (void)endUpdatesAnimated:(BOOL)animated completion:(nullable void (^)(BOOL))completion
{
ASDisplayNodeAssertMainThread();
ASDisplayNodeAssertNotNil(_changeSet, @"_changeSet must be available when batch update ends");
_batchUpdateCount--;
// Prevent calling endUpdatesAnimated:completion: in an unbalanced way
NSAssert(_batchUpdateCount >= 0, @"endUpdatesAnimated:completion: called without having a balanced beginUpdates call");
[_changeSet addCompletionHandler:completion];
if (_batchUpdateCount == 0) {
[_dataController updateWithChangeSet:_changeSet animated:animated];
_changeSet = nil;
}
}
- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion
{
ASDisplayNodeAssertMainThread();
[_dataController beginUpdates];
[self beginUpdates];
if (updates) {
updates();
}
[_dataController endUpdatesAnimated:animated completion:completion];
[self endUpdatesAnimated:animated completion:completion];
}
- (void)performBatchUpdates:(void (^)())updates completion:(void (^)(BOOL))completion
@@ -789,27 +836,35 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
{
ASDisplayNodeAssertMainThread();
if (sections.count == 0) { return; }
[_dataController insertSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet insertSections:sections animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)deleteSections:(NSIndexSet *)sections
{
ASDisplayNodeAssertMainThread();
if (sections.count == 0) { return; }
[_dataController deleteSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet deleteSections:sections animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)reloadSections:(NSIndexSet *)sections
{
ASDisplayNodeAssertMainThread();
if (sections.count == 0) { return; }
[_dataController reloadSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet reloadSections:sections animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection
{
ASDisplayNodeAssertMainThread();
[_dataController moveSection:section toSection:newSection withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet moveSection:section toSection:newSection animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (id<ASSectionContext>)contextForSection:(NSInteger)section
@@ -822,27 +877,35 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
{
ASDisplayNodeAssertMainThread();
if (indexPaths.count == 0) { return; }
[_dataController insertRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet insertItems:indexPaths animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths
{
ASDisplayNodeAssertMainThread();
if (indexPaths.count == 0) { return; }
[_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet deleteItems:indexPaths animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
{
ASDisplayNodeAssertMainThread();
if (indexPaths.count == 0) { return; }
[_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet reloadItems:indexPaths animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath
{
ASDisplayNodeAssertMainThread();
[_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:kASCollectionViewAnimationNone];
[self performBatchUpdates:^{
[_changeSet moveItemAtIndexPath:indexPath toIndexPath:newIndexPath animationOptions:kASCollectionViewAnimationNone];
} completion:nil];
}
#pragma mark -