From 9214e3c2efacb88ef9923fd9eb1caa1244d5ba2e Mon Sep 17 00:00:00 2001 From: Max Wang Date: Mon, 4 Jun 2018 10:29:41 -0700 Subject: [PATCH] Renew supplementary node on relayout (#842) * fix SIMULATE_WEB_RESPONSE not imported #449 * Fix to make rangeMode update in right time * Renew supplementary node on relayout. * Add support for layoutDelegate (ASCollectionLayout). * revert space * Update change log * fix build error * refactor * set default size * return early when can delegate --- CHANGELOG.md | 1 + Source/Details/ASDataController.mm | 62 +++++++++++++++++++++++++--- Source/Private/ASMutableElementMap.h | 2 + Source/Private/ASMutableElementMap.m | 5 +++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77daf16fd..8af2841ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## master * Add your own contributions to the next release on the line below this with your name. +- [ASDataController] Add capability to renew supplementary views (update map) when size change from zero to non-zero.[Max Wang](https://github.com/wsdwsd0829) [#842](https://github.com/TextureGroup/Texture/pull/842) - Make `ASPerformMainThreadDeallocation` visible in C. [Adlai Holler](https://github.com/Adlai-Holler) - Add snapshot test for astextnode2. [Max Wang](https://github.com/wsdwsd0829) [#935](https://github.com/TextureGroup/Texture/pull/935) - Internal housekeeping on the async transaction (rendering) system. [Adlai Holler](https://github.com/Adlai-Holler) diff --git a/Source/Details/ASDataController.mm b/Source/Details/ASDataController.mm index 84c600b6f..e1b25c634 100644 --- a/Source/Details/ASDataController.mm +++ b/Source/Details/ASDataController.mm @@ -25,6 +25,7 @@ #import #import #import +#import #import #import #import @@ -281,6 +282,50 @@ - (void)_repopulateSupplementaryNodesIntoMap:(ASMutableElementMap *)map } } +/** + * Update supplementary nodes of all kinds for sections. + * + * @param map The element map into which to apply the change. + * @param traitCollection The trait collection needed to initialize elements + * @param shouldFetchSizeRanges Whether constrained sizes should be fetched from data source + */ +- (void)_updateSupplementaryNodesIntoMap:(ASMutableElementMap *)map + traitCollection:(ASPrimitiveTraitCollection)traitCollection + shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges + previousMap:(ASElementMap *)previousMap +{ + ASDisplayNodeAssertMainThread(); + if (self.layoutDelegate != nil) { + // TODO: https://github.com/TextureGroup/Texture/issues/948 + return; + } + NSUInteger sectionCount = [self itemCountsFromDataSource].size(); + if (sectionCount > 0) { + NSIndexSet *sectionIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)]; + ASSizeRange newSizeRange = ASSizeRangeZero; + for (NSString *kind in [self supplementaryKindsInSections:sectionIndexes]) { + NSArray *indexPaths = [self _allIndexPathsForItemsOfKind:kind inSections:sectionIndexes]; + NSMutableArray *indexPathsToDeleteForKind = [[NSMutableArray alloc] init]; + NSMutableArray *indexPathsToInsertForKind = [[NSMutableArray alloc] init]; + // If supplementary node does exist and size is now zero, remove it. + // If supplementary node doesn't exist and size is now non-zero, insert one. + for (NSIndexPath *indexPath in indexPaths) { + ASCollectionElement *previousElement = [previousMap supplementaryElementOfKind:kind atIndexPath:indexPath]; + newSizeRange = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPath]; + BOOL sizeRangeIsZero = ASSizeRangeEqualToSizeRange(ASSizeRangeZero, newSizeRange); + if (previousElement != nil && sizeRangeIsZero) { + [indexPathsToDeleteForKind addObject:indexPath]; + } else if (previousElement == nil && !sizeRangeIsZero) { + [indexPathsToInsertForKind addObject:indexPath]; + } + } + + [map removeSupplementaryElementsAtIndexPaths:indexPathsToDeleteForKind kind:kind]; + [self _insertElementsIntoMap:map kind:kind atIndexPaths:indexPathsToInsertForKind traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges changeSet:nil previousMap:previousMap]; + } + } +} + /** * Inserts new elements of a certain kind for some sections * @@ -830,13 +875,20 @@ - (void)relayoutAllNodesWithInvalidationBlock:(nullable void (^)())invalidationB - (void)_relayoutAllNodes { ASDisplayNodeAssertMainThread(); + // Aggressively repopulate all supplemtary elements + // Assuming this method is run on the main serial queue, _pending and _visible maps are synced and can be manipulated directly. + ASDisplayNodeAssert(_visibleMap == _pendingMap, @"Expected visible and pending maps to be synchronized: %@", self); + + ASMutableElementMap *newMap = [_pendingMap mutableCopy]; + [self _updateSupplementaryNodesIntoMap:newMap + traitCollection:[self.node primitiveTraitCollection] + shouldFetchSizeRanges:YES + previousMap:_pendingMap]; + _pendingMap = [newMap copy]; + _visibleMap = _pendingMap; + for (ASCollectionElement *element in _visibleMap) { - // Ignore this element if it is no longer in the latest data. It is still recognized in the UIKit world but will be deleted soon. NSIndexPath *indexPathInPendingMap = [_pendingMap indexPathForElement:element]; - if (indexPathInPendingMap == nil) { - continue; - } - NSString *kind = element.supplementaryElementKind ?: ASDataControllerRowNodeKind; ASSizeRange newConstrainedSize = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPathInPendingMap]; diff --git a/Source/Private/ASMutableElementMap.h b/Source/Private/ASMutableElementMap.h index 10225a455..a4c3b3e02 100644 --- a/Source/Private/ASMutableElementMap.h +++ b/Source/Private/ASMutableElementMap.h @@ -48,6 +48,8 @@ AS_SUBCLASSING_RESTRICTED - (void)removeSectionsOfItems:(NSIndexSet *)itemSections; +- (void)removeSupplementaryElementsAtIndexPaths:(NSArray *)indexPaths kind:(NSString *)kind; + - (void)insertEmptySectionsOfItemsAtIndexes:(NSIndexSet *)sections; - (void)insertElement:(ASCollectionElement *)element atIndexPath:(NSIndexPath *)indexPath; diff --git a/Source/Private/ASMutableElementMap.m b/Source/Private/ASMutableElementMap.m index c7742bbec..1ddbc1272 100644 --- a/Source/Private/ASMutableElementMap.m +++ b/Source/Private/ASMutableElementMap.m @@ -68,6 +68,11 @@ - (void)removeSectionsAtIndexes:(NSIndexSet *)indexes [_sections removeObjectsAtIndexes:indexes]; } +- (void)removeSupplementaryElementsAtIndexPaths:(NSArray *)indexPaths kind:(NSString *)kind +{ + [_supplementaryElements[kind] removeObjectsForKeys:indexPaths]; +} + - (void)removeAllElements { [_sectionsOfItems removeAllObjects];