@@ -130,7 +130,8 @@ - (void)_updateVisibleNodeIndexPaths
130130 rangeType: rangeType];
131131
132132 // Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths
133- NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy ] : [NSMutableSet set ];
133+ // This value may be nil for the first call of this method.
134+ NSMutableSet *removedIndexPaths = [_rangeTypeIndexPaths[rangeKey] mutableCopy ];
134135 [removedIndexPaths minusSet: indexPaths];
135136 [removedIndexPaths minusSet: visibleNodePathsSet];
136137
@@ -176,61 +177,76 @@ - (BOOL)shouldSkipVisibleNodesForRangeType:(ASLayoutRangeType)rangeType
176177
177178#pragma mark - ASDataControllerDelegete
178179
179- - (void )dataControllerBeginUpdates : (ASDataController *)dataController {
180+ - (void )dataControllerBeginUpdates : (ASDataController *)dataController
181+ {
180182 ASPerformBlockOnMainThread (^{
181183 [_delegate didBeginUpdatesInRangeController: self ];
182184 });
183185}
184186
185- - (void )dataController : (ASDataController *)dataController endUpdatesAnimated : (BOOL )animated completion : (void (^)(BOOL ))completion {
187+ - (void )dataController : (ASDataController *)dataController endUpdatesAnimated : (BOOL )animated completion : (void (^)(BOOL ))completion
188+ {
186189 ASPerformBlockOnMainThread (^{
187190 [_delegate rangeController: self didEndUpdatesAnimated: animated completion: completion];
188191 });
189192}
190193
191- - (void )dataController : (ASDataController *)dataController didInsertNodes : (NSArray *)nodes atIndexPaths : (NSArray *)indexPaths withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions {
194+ - (void )dataController : (ASDataController *)dataController didInsertNodes : (NSArray *)nodes atIndexPaths : (NSArray *)indexPaths withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions
195+ {
192196 ASDisplayNodeAssert (nodes.count == indexPaths.count , @" Invalid index path" );
193-
194- NSMutableArray *nodeSizes = [NSMutableArray arrayWithCapacity: nodes.count];
195- [nodes enumerateObjectsUsingBlock: ^(ASCellNode *node, NSUInteger idx, BOOL *stop) {
196- [nodeSizes addObject: [NSValue valueWithCGSize: node.calculatedSize]];
197- }];
198-
199197 ASPerformBlockOnMainThread (^{
200198 _rangeIsValid = NO ;
201199 [_delegate rangeController: self didInsertNodes: nodes atIndexPaths: indexPaths withAnimationOptions: animationOptions];
202200 });
203201}
204202
205- - (void )dataController : (ASDataController *)dataController didDeleteNodes : (NSArray *)nodes atIndexPaths : (NSArray *)indexPaths withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions {
203+ - (void )dataController : (ASDataController *)dataController didDeleteNodes : (NSArray *)nodes atIndexPaths : (NSArray *)indexPaths withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions
204+ {
206205 ASPerformBlockOnMainThread (^{
207206 _rangeIsValid = NO ;
207+
208+ // When removing nodes we need to make sure that removed indexPaths are not left in _rangeTypeIndexPaths,
209+ // otherwise _updateVisibleNodeIndexPaths may try to retrieve nodes from dataSource that aren't there anymore
210+ for (NSInteger i = 0 ; i < ASLayoutRangeTypeCount; i++) {
211+ id rangeKey = @((ASLayoutRangeType)i);
212+ NSMutableSet *rangePaths = [_rangeTypeIndexPaths[rangeKey] mutableCopy ];
213+ for (NSIndexPath *path in indexPaths) {
214+ [rangePaths removeObject: path];
215+ }
216+ _rangeTypeIndexPaths[rangeKey] = rangePaths;
217+ }
218+
208219 [_delegate rangeController: self didDeleteNodes: nodes atIndexPaths: indexPaths withAnimationOptions: animationOptions];
209220 });
210221}
211222
212- - (void )dataController : (ASDataController *)dataController didInsertSections : (NSArray *)sections atIndexSet : (NSIndexSet *)indexSet withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions {
223+ - (void )dataController : (ASDataController *)dataController didInsertSections : (NSArray *)sections atIndexSet : (NSIndexSet *)indexSet withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions
224+ {
213225 ASDisplayNodeAssert (sections.count == indexSet.count , @" Invalid sections" );
214-
215- NSMutableArray *sectionNodeSizes = [NSMutableArray arrayWithCapacity: sections.count];
216-
217- [sections enumerateObjectsUsingBlock: ^(NSArray *nodes, NSUInteger idx, BOOL *stop) {
218- NSMutableArray *nodeSizes = [NSMutableArray arrayWithCapacity: nodes.count];
219- [nodes enumerateObjectsUsingBlock: ^(ASCellNode *node, NSUInteger idx2, BOOL *stop2) {
220- [nodeSizes addObject: [NSValue valueWithCGSize: node.calculatedSize]];
221- }];
222- [sectionNodeSizes addObject: nodeSizes];
223- }];
224-
225226 ASPerformBlockOnMainThread (^{
226227 _rangeIsValid = NO ;
227228 [_delegate rangeController: self didInsertSectionsAtIndexSet: indexSet withAnimationOptions: animationOptions];
228229 });
229230}
230231
231- - (void )dataController : (ASDataController *)dataController didDeleteSectionsAtIndexSet : (NSIndexSet *)indexSet withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions {
232+ - (void )dataController : (ASDataController *)dataController didDeleteSectionsAtIndexSet : (NSIndexSet *)indexSet withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions
233+ {
232234 ASPerformBlockOnMainThread (^{
233235 _rangeIsValid = NO ;
236+
237+ // When removing nodes we need to make sure that removed indexPaths are not left in _rangeTypeIndexPaths,
238+ // otherwise _updateVisibleNodeIndexPaths may try to retrieve nodes from dataSource that aren't there anymore
239+ for (NSInteger i = 0 ; i < ASLayoutRangeTypeCount; i++) {
240+ id rangeKey = @((ASLayoutRangeType)i);
241+ NSMutableSet *rangePaths = [_rangeTypeIndexPaths[rangeKey] mutableCopy ];
242+ for (NSIndexPath *path in _rangeTypeIndexPaths[rangeKey]) {
243+ if ([indexSet containsIndex: path.section]) {
244+ [rangePaths removeObject: path];
245+ }
246+ }
247+ _rangeTypeIndexPaths[rangeKey] = rangePaths;
248+ }
249+
234250 [_delegate rangeController: self didDeleteSectionsAtIndexSet: indexSet withAnimationOptions: animationOptions];
235251 });
236252}
0 commit comments