mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
[ASDataController] Add validation logic to the change set to throw exceptions on invalid updates (#1894)
[_ASHierarchyChangeSet] Oopsy daisy [ASDataController] Tweak our update validation [ASHierarchyChangeSet] Fix bugs Finish up some stuff [ASDataController] Put some stuff back [ASChangeSetDataController] Always use changeset [ASDataController] Put other stuff back [_ASHierarchyChangeSet] Use fast enumeration [_ASHierarchyChangeSet] Fix assertion format strings, return on fail so we don't crash in production [ASDataController] Store data source item counts as vector rather than NSArray [ASDataController] Build some tests for the update validation [ASDataController] Fix issues with update validation Get rid of new file [ASDataController] Suppress changeset validation before initial reload [ASDataController] Make invalid update log vs. exception publicly toggleable
This commit is contained in:
160
AsyncDisplayKit/Details/ASChangeSetDataController.mm
Normal file
160
AsyncDisplayKit/Details/ASChangeSetDataController.mm
Normal file
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// ASChangeSetDataController.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Huy Nguyen on 19/10/15.
|
||||
//
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import "ASChangeSetDataController.h"
|
||||
#import "_ASHierarchyChangeSet.h"
|
||||
#import "ASAssert.h"
|
||||
#import "ASDataController+Subclasses.h"
|
||||
|
||||
@implementation ASChangeSetDataController {
|
||||
NSInteger _changeSetBatchUpdateCounter;
|
||||
_ASHierarchyChangeSet *_changeSet;
|
||||
}
|
||||
|
||||
#pragma mark - Batching (External API)
|
||||
|
||||
- (void)beginUpdates
|
||||
{
|
||||
// NOTE: This assertion is failing in some apps and will be enabled soon.
|
||||
// ASDisplayNodeAssertMainThread();
|
||||
if (_changeSetBatchUpdateCounter <= 0) {
|
||||
_changeSetBatchUpdateCounter = 0;
|
||||
_changeSet = [[_ASHierarchyChangeSet alloc] initWithOldData:[self itemCountsFromDataSource]];
|
||||
}
|
||||
_changeSetBatchUpdateCounter++;
|
||||
}
|
||||
|
||||
- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion
|
||||
{
|
||||
// NOTE: This assertion is failing in some apps and will be enabled soon.
|
||||
// ASDisplayNodeAssertMainThread();
|
||||
_changeSetBatchUpdateCounter--;
|
||||
|
||||
// Prevent calling endUpdatesAnimated:completion: in an unbalanced way
|
||||
// NOTE: This assertion is failing in some apps and will be enabled soon.
|
||||
// NSAssert(_changeSetBatchUpdateCounter >= 0, @"endUpdatesAnimated:completion: called without having a balanced beginUpdates call");
|
||||
|
||||
if (_changeSetBatchUpdateCounter == 0) {
|
||||
if (!self.initialReloadDataHasBeenCalled) {
|
||||
if (completion) {
|
||||
completion(YES);
|
||||
}
|
||||
_changeSet = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
[self invalidateDataSourceItemCounts];
|
||||
[_changeSet markCompletedWithNewItemCounts:[self itemCountsFromDataSource]];
|
||||
|
||||
[super beginUpdates];
|
||||
|
||||
for (_ASHierarchyItemChange *change in [_changeSet itemChangesOfType:_ASHierarchyChangeTypeDelete]) {
|
||||
[super deleteRowsAtIndexPaths:change.indexPaths withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
for (_ASHierarchySectionChange *change in [_changeSet sectionChangesOfType:_ASHierarchyChangeTypeDelete]) {
|
||||
[super deleteSections:change.indexSet withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
for (_ASHierarchySectionChange *change in [_changeSet sectionChangesOfType:_ASHierarchyChangeTypeInsert]) {
|
||||
[super insertSections:change.indexSet withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
for (_ASHierarchyItemChange *change in [_changeSet itemChangesOfType:_ASHierarchyChangeTypeInsert]) {
|
||||
[super insertRowsAtIndexPaths:change.indexPaths withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
[super endUpdatesAnimated:animated completion:completion];
|
||||
|
||||
_changeSet = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)batchUpdating
|
||||
{
|
||||
BOOL batchUpdating = (_changeSetBatchUpdateCounter != 0);
|
||||
// _changeSet must be available during batch update
|
||||
ASDisplayNodeAssertTrue(batchUpdating == (_changeSet != nil));
|
||||
return batchUpdating;
|
||||
}
|
||||
|
||||
#pragma mark - Section Editing (External API)
|
||||
|
||||
- (void)insertSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet insertSections:sections animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)deleteSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet deleteSections:sections animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)reloadSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet reloadSections:sections animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet deleteSections:[NSIndexSet indexSetWithIndex:section] animationOptions:animationOptions];
|
||||
[_changeSet insertSections:[NSIndexSet indexSetWithIndex:newSection] animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
#pragma mark - Row Editing (External API)
|
||||
|
||||
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet insertItems:indexPaths animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet deleteItems:indexPaths animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet reloadItems:indexPaths animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self beginUpdates];
|
||||
[_changeSet deleteItems:@[indexPath] animationOptions:animationOptions];
|
||||
[_changeSet insertItems:@[newIndexPath] animationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user