@@ -173,8 +173,11 @@ @interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDe
173173 unsigned int collectionNodeWillDisplaySupplementaryElement:1 ;
174174 unsigned int collectionNodeDidEndDisplayingSupplementaryElement:1 ;
175175 unsigned int shouldBatchFetchForCollectionNode:1 ;
176- // Whether this delegate conforms to ASCollectionDataSourceInterop
176+
177+ // Interop flags
177178 unsigned int interop:1 ;
179+ unsigned int interopWillDisplayCell:1 ;
180+ unsigned int interopDidEndDisplayingCell:1 ;
178181 } _asyncDelegateFlags;
179182
180183 struct {
@@ -193,6 +196,10 @@ @interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDe
193196
194197 // Whether this data source conforms to ASCollectionDataSourceInterop
195198 unsigned int interop:1 ;
199+ // Whether this interop data source returns YES from +dequeuesCellsForNodeBackedItems
200+ unsigned int interopAlwaysDequeue:1 ;
201+ // Whether this interop data source implements viewForSupplementaryElementOfKind:
202+ unsigned int interopViewForSupplementaryElement:1 ;
196203 } _asyncDataSourceFlags;
197204
198205 struct {
@@ -411,7 +418,13 @@ - (void)setAsyncDataSource:(id<ASCollectionDataSource>)asyncDataSource
411418 _asyncDataSourceFlags.collectionNodeContextForSection = [_asyncDataSource respondsToSelector: @selector (collectionNode:contextForSection: )];
412419 _asyncDataSourceFlags.collectionNodeNodeForSupplementaryElement = [_asyncDataSource respondsToSelector: @selector (collectionNode:nodeForSupplementaryElementOfKind:atIndexPath: )];
413420 _asyncDataSourceFlags.collectionNodeSupplementaryElementKindsInSection = [_asyncDataSource respondsToSelector: @selector (collectionNode:supplementaryElementKindsInSection: )];
421+
414422 _asyncDataSourceFlags.interop = [_asyncDataSource conformsToProtocol: @protocol (ASCollectionDataSourceInterop)];
423+ if (_asyncDataSourceFlags.interop ) {
424+ id <ASCollectionDataSourceInterop> interopDataSource = (id <ASCollectionDataSourceInterop>)_asyncDataSource;
425+ _asyncDataSourceFlags.interopAlwaysDequeue = [[interopDataSource class ] respondsToSelector: @selector (dequeuesCellsForNodeBackedItems )] && [[interopDataSource class ] dequeuesCellsForNodeBackedItems ];
426+ _asyncDataSourceFlags.interopViewForSupplementaryElement = [interopDataSource respondsToSelector: @selector (collectionView:viewForSupplementaryElementOfKind:atIndexPath: )];
427+ }
415428
416429 ASDisplayNodeAssert (_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection || _asyncDataSourceFlags.collectionViewNumberOfItemsInSection , @" Data source must implement collectionNode:numberOfItemsInSection:" );
417430 ASDisplayNodeAssert (_asyncDataSourceFlags.collectionNodeNodeBlockForItem
@@ -490,6 +503,11 @@ - (void)setAsyncDelegate:(id<ASCollectionDelegate>)asyncDelegate
490503 _asyncDelegateFlags.collectionNodeCanPerformActionForItem = [_asyncDelegate respondsToSelector: @selector (collectionNode:canPerformAction:forItemAtIndexPath:sender: )];
491504 _asyncDelegateFlags.collectionNodePerformActionForItem = [_asyncDelegate respondsToSelector: @selector (collectionNode:performAction:forItemAtIndexPath:sender: )];
492505 _asyncDelegateFlags.interop = [_asyncDelegate conformsToProtocol: @protocol (ASCollectionDelegateInterop)];
506+ if (_asyncDelegateFlags.interop ) {
507+ id <ASCollectionDelegateInterop> interopDelegate = (id <ASCollectionDelegateInterop>)_asyncDelegate;
508+ _asyncDelegateFlags.interopWillDisplayCell = [interopDelegate respondsToSelector: @selector (collectionView:willDisplayCell:forItemAtIndexPath: )];
509+ _asyncDelegateFlags.interopDidEndDisplayingCell = [interopDelegate respondsToSelector: @selector (collectionView:didEndDisplayingCell:forItemAtIndexPath: )];
510+ }
493511 }
494512
495513 super.delegate = (id <UICollectionViewDelegate>)_proxyDelegate;
@@ -882,20 +900,26 @@ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollection
882900
883901- (UICollectionReusableView *)collectionView : (UICollectionView *)collectionView viewForSupplementaryElementOfKind : (NSString *)kind atIndexPath : (NSIndexPath *)indexPath
884902{
903+ if ([_registeredSupplementaryKinds containsObject: kind] == NO ) {
904+ [self registerSupplementaryNodeOfKind: kind];
905+ }
906+
885907 UICollectionReusableView *view = nil ;
886908 ASCellNode *node = [_dataController supplementaryNodeOfKind: kind atIndexPath: indexPath];
887909
888- if (node.shouldUseUIKitCell && _asyncDataSourceFlags.interop ) {
910+ BOOL shouldDequeueExternally = _asyncDataSourceFlags.interopViewForSupplementaryElement && (_asyncDataSourceFlags.interopAlwaysDequeue || node.shouldUseUIKitCell );
911+ if (shouldDequeueExternally) {
889912 view = [(id <ASCollectionDataSourceInterop>)_asyncDataSource collectionView: collectionView viewForSupplementaryElementOfKind: kind atIndexPath: indexPath];
890913 } else {
891- ASDisplayNodeAssert (node != nil , @" Supplementary node should exist. Kind = %@ , indexPath = %@ , collectionDataSource = %@ " , kind, indexPath, self);
892- if ([_registeredSupplementaryKinds containsObject: kind] == NO ) {
893- [self registerSupplementaryNodeOfKind: kind];
894- }
895914 view = [self dequeueReusableSupplementaryViewOfKind: kind withReuseIdentifier: kReuseIdentifier forIndexPath: indexPath];
896- if (node) {
897- [_rangeController configureContentView: view forCellNode: node];
898- }
915+ }
916+
917+ if (!node.shouldUseUIKitCell ) {
918+ ASDisplayNodeAssert (node != nil , @" Supplementary node should exist. Kind = %@ , indexPath = %@ , collectionDataSource = %@ " , kind, indexPath, self);
919+ }
920+
921+ if (node) {
922+ [_rangeController configureContentView: view forCellNode: node];
899923 }
900924
901925 return view;
@@ -906,25 +930,32 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
906930 UICollectionViewCell *cell = nil ;
907931 ASCellNode *node = [self nodeForItemAtIndexPath: indexPath];
908932
909- if (node.shouldUseUIKitCell && _asyncDataSourceFlags.interop ) {
933+ BOOL shouldDequeueExternally = _asyncDataSourceFlags.interopAlwaysDequeue || (_asyncDataSourceFlags.interop && node.shouldUseUIKitCell );
934+ if (shouldDequeueExternally) {
910935 cell = [(id <ASCollectionDataSourceInterop>)_asyncDataSource collectionView: collectionView cellForItemAtIndexPath: indexPath];
911936 } else {
912- ASDisplayNodeAssert (node != nil , @" Cell node should exist. indexPath = %@ , collectionDataSource = %@ " , indexPath, self);
913937 cell = [self dequeueReusableCellWithReuseIdentifier: kReuseIdentifier forIndexPath: indexPath];
914- [(_ASCollectionViewCell *)cell setNode: node];
938+ }
939+
940+ ASDisplayNodeAssert (node != nil , @" Cell node should exist. indexPath = %@ , collectionDataSource = %@ " , indexPath, self);
941+
942+ if (_ASCollectionViewCell *asCell = ASDynamicCast (cell, _ASCollectionViewCell)) {
943+ asCell.node = node;
915944 [_rangeController configureContentView: cell.contentView forCellNode: node];
916945 }
946+
917947 return cell;
918948}
919949
920950- (void )collectionView : (UICollectionView *)collectionView willDisplayCell : (_ASCollectionViewCell *)cell forItemAtIndexPath : (NSIndexPath *)indexPath
921951{
952+ if (_asyncDelegateFlags.interopWillDisplayCell ) {
953+ [(id <ASCollectionDelegateInterop>)_asyncDelegate collectionView: collectionView willDisplayCell: cell forItemAtIndexPath: indexPath];
954+ }
955+
922956 // Since _ASCollectionViewCell is not available for subclassing, this is faster than isKindOfClass:
923957 // We must exit early here, because only _ASCollectionViewCell implements the -node accessor method.
924958 if ([cell class ] != [_ASCollectionViewCell class ]) {
925- if (_asyncDelegateFlags.interop ) {
926- [(id <ASCollectionDelegateInterop>)_asyncDelegate collectionView: collectionView willDisplayCell: cell forItemAtIndexPath: indexPath];
927- }
928959 [_rangeController setNeedsUpdate ];
929960 return ;
930961 }
@@ -963,12 +994,13 @@ - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(_ASCo
963994
964995- (void )collectionView : (UICollectionView *)collectionView didEndDisplayingCell : (_ASCollectionViewCell *)cell forItemAtIndexPath : (NSIndexPath *)indexPath
965996{
997+ if (_asyncDelegateFlags.interopDidEndDisplayingCell ) {
998+ [(id <ASCollectionDelegateInterop>)_asyncDelegate collectionView: collectionView didEndDisplayingCell: cell forItemAtIndexPath: indexPath];
999+ }
1000+
9661001 // Since _ASCollectionViewCell is not available for subclassing, this is faster than isKindOfClass:
9671002 // We must exit early here, because only _ASCollectionViewCell implements the -node accessor method.
9681003 if ([cell class ] != [_ASCollectionViewCell class ]) {
969- if (_asyncDelegateFlags.interop ) {
970- [(id <ASCollectionDelegateInterop>)_asyncDelegate collectionView: collectionView didEndDisplayingCell: cell forItemAtIndexPath: indexPath];
971- }
9721004 [_rangeController setNeedsUpdate ];
9731005 return ;
9741006 }
0 commit comments