-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Ensure that newly inserted section supplementary nodes are added to backing store #917
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,22 +28,30 @@ @implementation ASCollectionDataController { | |
NSMutableDictionary *_pendingIndexPaths; | ||
} | ||
|
||
- (void)prepareForReloadData | ||
- (instancetype)initWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled | ||
{ | ||
_pendingNodes = [NSMutableDictionary dictionary]; | ||
_pendingIndexPaths = [NSMutableDictionary dictionary]; | ||
self = [super initWithAsyncDataFetching:asyncDataFetchingEnabled]; | ||
if (self != nil) { | ||
_pendingNodes = [NSMutableDictionary dictionary]; | ||
_pendingIndexPaths = [NSMutableDictionary dictionary]; | ||
} | ||
return self; | ||
} | ||
|
||
[[self supplementaryKinds] enumerateObjectsUsingBlock:^(NSString *kind, NSUInteger idx, BOOL *stop) { | ||
- (void)prepareForReloadData | ||
{ | ||
NSArray *kinds = [self supplementaryKinds]; | ||
for (NSString *kind in kinds) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for using fast enumeration! No need for block overhead. In this case I think it would be OK (although not much better) to call [self supplementaryKinds] in the for (), as it will only be called once. |
||
LOG(@"Populating elements of kind: %@", kind); | ||
NSMutableArray *indexPaths = [NSMutableArray array]; | ||
NSMutableArray *nodes = [NSMutableArray array]; | ||
[self _populateSupplementaryNodesOfKind:kind withMutableNodes:nodes mutableIndexPaths:indexPaths]; | ||
_pendingNodes[kind] = nodes; | ||
_pendingIndexPaths[kind] = indexPaths; | ||
|
||
// Measure loaded nodes before leaving the main thread | ||
[self layoutLoadedNodes:nodes ofKind:kind atIndexPaths:indexPaths]; | ||
}]; | ||
} | ||
} | ||
|
||
- (void)willReloadData | ||
|
@@ -56,7 +64,7 @@ - (void)willReloadData | |
NSArray *editingNodes = [self editingNodesOfKind:kind]; | ||
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, editingNodes.count)]; | ||
[self deleteSectionsOfKind:kind atIndexSet:indexSet completion:nil]; | ||
|
||
// Insert each section | ||
NSUInteger sectionCount = [self.collectionDataSource dataController:self numberOfSectionsForSupplementaryNodeOfKind:kind]; | ||
NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount]; | ||
|
@@ -75,7 +83,8 @@ - (void)willReloadData | |
|
||
- (void)prepareForInsertSections:(NSIndexSet *)sections | ||
{ | ||
[[self supplementaryKinds] enumerateObjectsUsingBlock:^(NSString *kind, NSUInteger idx, BOOL *stop) { | ||
NSArray *kinds = [self supplementaryKinds]; | ||
for (NSString *kind in kinds) { | ||
LOG(@"Populating elements of kind: %@, for sections: %@", kind, sections); | ||
NSMutableArray *nodes = [NSMutableArray array]; | ||
NSMutableArray *indexPaths = [NSMutableArray array]; | ||
|
@@ -85,7 +94,7 @@ - (void)prepareForInsertSections:(NSIndexSet *)sections | |
|
||
// Measure loaded nodes before leaving the main thread | ||
[self layoutLoadedNodes:nodes ofKind:kind atIndexPaths:indexPaths]; | ||
}]; | ||
} | ||
} | ||
|
||
- (void)willInsertSections:(NSIndexSet *)sections | ||
|
@@ -97,25 +106,29 @@ - (void)willInsertSections:(NSIndexSet *)sections | |
} | ||
|
||
[self insertSections:sectionArray ofKind:kind atIndexSet:sections completion:nil]; | ||
[self batchLayoutNodes:nodes ofKind:kind atIndexPaths:_pendingIndexPaths[kind] completion:nil]; | ||
_pendingNodes[kind] = nil; | ||
_pendingIndexPaths[kind] = nil; | ||
[self batchLayoutNodes:nodes ofKind:kind atIndexPaths:_pendingIndexPaths[kind] completion:^(NSArray *nodes, NSArray *indexPaths) { | ||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil]; | ||
}]; | ||
[_pendingNodes removeObjectForKey:kind]; | ||
[_pendingIndexPaths removeObjectForKey:kind]; | ||
}]; | ||
} | ||
|
||
- (void)willDeleteSections:(NSIndexSet *)sections | ||
{ | ||
[[self supplementaryKinds] enumerateObjectsUsingBlock:^(NSString *kind, NSUInteger idx, BOOL *stop) { | ||
NSArray *kinds = [self supplementaryKinds]; | ||
for (NSString *kind in kinds) { | ||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections); | ||
|
||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; | ||
[self deleteSectionsOfKind:kind atIndexSet:sections completion:nil]; | ||
}]; | ||
} | ||
} | ||
|
||
- (void)prepareForReloadSections:(NSIndexSet *)sections | ||
{ | ||
[[self supplementaryKinds] enumerateObjectsUsingBlock:^(NSString *kind, NSUInteger idx, BOOL *stop) { | ||
NSArray *kinds = [self supplementaryKinds]; | ||
for (NSString *kind in kinds) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I see you did the whole file - which is badass!! - it probably would be better to save the lines and do the self call inline with the for (). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup good idea. |
||
NSMutableArray *nodes = [NSMutableArray array]; | ||
NSMutableArray *indexPaths = [NSMutableArray array]; | ||
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableNodes:nodes mutableIndexPaths:indexPaths]; | ||
|
@@ -124,7 +137,7 @@ - (void)prepareForReloadSections:(NSIndexSet *)sections | |
|
||
// Measure loaded nodes before leaving the main thread | ||
[self layoutLoadedNodes:nodes ofKind:kind atIndexPaths:indexPaths]; | ||
}]; | ||
} | ||
} | ||
|
||
- (void)willReloadSections:(NSIndexSet *)sections | ||
|
@@ -134,14 +147,15 @@ - (void)willReloadSections:(NSIndexSet *)sections | |
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; | ||
// reinsert the elements | ||
[self batchLayoutNodes:nodes ofKind:kind atIndexPaths:_pendingIndexPaths[kind] completion:nil]; | ||
_pendingNodes[kind] = nil; | ||
_pendingIndexPaths[kind] = nil; | ||
[_pendingNodes removeObjectForKey:kind]; | ||
[_pendingIndexPaths removeObjectForKey:kind]; | ||
}]; | ||
} | ||
|
||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection | ||
{ | ||
[[self supplementaryKinds] enumerateObjectsUsingBlock:^(NSString *kind, NSUInteger idx, BOOL *stop) { | ||
NSArray *kinds = [self supplementaryKinds]; | ||
for (NSString *kind in kinds) { | ||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], [NSIndexSet indexSetWithIndex:section]); | ||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths([self editingNodesOfKind:kind], indexPaths); | ||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; | ||
|
@@ -153,7 +167,7 @@ - (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection | |
[updatedIndexPaths addObject:[sectionIndexPath indexPathByAddingIndex:[indexPath indexAtPosition:indexPath.length - 1]]]; | ||
}]; | ||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil]; | ||
}]; | ||
} | ||
} | ||
|
||
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withMutableNodes:(NSMutableArray *)nodes mutableIndexPaths:(NSMutableArray *)indexPaths | ||
|
@@ -214,4 +228,4 @@ - (NSArray *)supplementaryKinds | |
return (id<ASCollectionDataControllerSource>)self.dataSource; | ||
} | ||
|
||
@end | ||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this potentially get called multiple times, and need to recreate the _pendingNodes and _pendingIndexPaths dictionaries?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pending dictionaries exist to keep the pending state between the
prepare
andwill
methods. I've set them up to be created at initialization such that they'll remain throughout the lifetime of the collection data controller. Their contents are cleared out at the end of thewill
methods.