From 3fe29e8e11a817514d4a0b81f5e5903c74498c83 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 11 Oct 2016 13:38:53 -0700 Subject: [PATCH] More porting --- AsyncDisplayKit/ASCollectionNode.h | 262 +++++++++++- AsyncDisplayKit/ASCollectionView.h | 166 +------- AsyncDisplayKit/ASCollectionView.mm | 403 ++++++++++++------ AsyncDisplayKit/ASCollectionViewProtocols.h | 36 +- AsyncDisplayKit/ASPagerNode.m | 6 +- AsyncDisplayKit/ASTableNode.h | 240 +++++++++++ AsyncDisplayKit/ASTableView.h | 240 ----------- .../ASCollectionViewFlowLayoutInspector.m | 11 +- AsyncDisplayKit/Details/ASDelegateProxy.m | 14 +- ...ASCollectionViewFlowLayoutInspectorTests.m | 7 +- AsyncDisplayKitTests/ASCollectionViewTests.mm | 9 +- 11 files changed, 820 insertions(+), 574 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index b74f905e7c..6c2def9d70 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -254,21 +254,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)reloadDataWithCompletion:(nullable void (^)())completion; -/** - * Reload everything from scratch, destroying the working range and all cached nodes. - * - * @warning This method is substantially more expensive than UICollectionView's version. - */ -- (void)reloadData; - -/** - * Reload everything from scratch entirely on the main thread, destroying the working range and all cached nodes. - * - * @warning This method is substantially more expensive than UICollectionView's version and will block the main thread - * while all the cells load. - */ -- (void)reloadDataImmediately; - #pragma mark - Querying Data /** @@ -324,4 +309,251 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * This is a node-based UICollectionViewDataSource. + */ +@protocol ASCollectionDataSource + +@optional + +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section; + +- (NSInteger)numberOfSectionsInCollectionNode:(ASCollectionNode *)collectionNode; + +/** + * Similar to -collectionView:nodeForItemAtIndexPath: + * This method takes precedence over collectionView:nodeForItemAtIndexPath: if implemented. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a block that creates the node for display at this indexpath. + * Must be thread-safe (can be called on the main thread or a background + * queue) and should not implement reuse (it will be called once per row). + */ +- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Similar to -collectionView:cellForItemAtIndexPath:. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a node for display at this indexpath. This will be called on the main thread and should + * not implement reuse (it will be called once per row). Unlike UICollectionView's version, + * this method is not called when the row is about to display. + */ +- (ASCellNode *)collectionNode:(ASCollectionNode *)collectionNode nodeForItemAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Asks the collection view to provide a supplementary node to display in the collection view. + * + * @param collectionView An object representing the collection view requesting this information. + * @param kind The kind of supplementary node to provide. + * @param indexPath The index path that specifies the location of the new supplementary node. + */ +- (ASCellNode *)collectionNode:(ASCollectionNode *)collectionNode nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath; + +/** + * Similar to -collectionView:cellForItemAtIndexPath:. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a node for display at this indexpath. This will be called on the main thread and should + * not implement reuse (it will be called once per row). Unlike UICollectionView's version, + * this method is not called when the row is about to display. + */ +- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Similar to -collectionView:nodeForItemAtIndexPath: + * This method takes precedence over collectionView:nodeForItemAtIndexPath: if implemented. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a block that creates the node for display at this indexpath. + * Must be thread-safe (can be called on the main thread or a background + * queue) and should not implement reuse (it will be called once per row). + */ +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Asks the collection view to provide a supplementary node to display in the collection view. + * + * @param collectionView An object representing the collection view requesting this information. + * @param kind The kind of supplementary node to provide. + * @param indexPath The index path that specifies the location of the new supplementary node. + */ +- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * TODO: Docs + */ +- (nullable id)collectionNode:(ASCollectionNode *)collectionNode contextForSection:(NSInteger)section; + +/** + * Indicator to lock the data source for data fetching in async mode. + * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception + * due to the data access in async mode. + * + * @param collectionView The sender. + * @deprecated The data source is always accessed on the main thread, and this method will not be called. + */ +- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; + +/** + * Indicator to unlock the data source for data fetching in async mode. + * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception + * due to the data access in async mode. + * + * @param collectionView The sender. + * @deprecated The data source is always accessed on the main thread, and this method will not be called. + */ +- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; + +@end + +/** + * This is a node-based UICollectionViewDelegate. + */ +@protocol ASCollectionDelegate + +@optional + +/** + * Provides the constrained size range for measuring the node at the index path. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the node. + * + * @return A constrained size range for layout the node at this index path. + */ +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath; + +- (void)collectionNode:(ASCollectionNode *)collectionNode willDisplayItemWithNode:(ASCellNode *)node; + +- (void)collectionNode:(ASCollectionNode *)collectionNode didEndDisplayingItemWithNode:(ASCellNode *)node; + +- (BOOL)collectionNode:(ASCollectionNode *)collectionNode shouldHighlightItemWithNode:(ASCellNode *)node; +- (void)collectionNode:(ASCollectionNode *)collectionNode didHighlightItemWithNode:(ASCellNode *)node; +- (void)collectionNode:(ASCollectionNode *)collectionNode didUnhighlightItemWithNode:(ASCellNode *)node; +- (BOOL)collectionNode:(ASCollectionNode *)collectionNode shouldSelectItemWithNode:(ASCellNode *)node; +- (BOOL)collectionNode:(ASCollectionNode *)collectionNode shouldDeselectItemWithNode:(ASCellNode *)node; +- (void)collectionNode:(ASCollectionNode *)collectionNode didSelectItemWithNode:(ASCellNode *)node; +- (void)collectionNode:(ASCollectionNode *)collectionNode didDeselectItemWithNode:(ASCellNode *)node; + +- (void)collectionNode:(ASCollectionNode *)collectionNode willDisplaySupplementaryElementWithNode:(ASCellNode *)node NS_AVAILABLE_IOS(8_0); +- (void)collectionNode:(ASCollectionNode *)collectionNode didEndDisplayingSupplementaryElementWithNode:(ASCellNode *)node; + +- (BOOL)collectionNode:(ASCollectionNode *)collectionNode shouldShowMenuForItemWithNode:(ASCellNode *)node; +- (BOOL)collectionNode:(ASCollectionNode *)collectionNode canPerformAction:(SEL)action forItemWithNode:(ASCellNode *)node sender:(nullable id)sender; +- (void)collectionNode:(ASCollectionNode *)collectionNode performAction:(SEL)action forItemWithNode:(ASCellNode *)node sender:(nullable id)sender; + +/** + * Receive a message that the collection node is near the end of its data set and more data should be fetched if + * necessary. + * + * @param collectionNode The sender. + * @param context A context object that must be notified when the batch fetch is completed. + * + * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future + * notifications to do batch fetches. This method is called on a background queue. + * + * ASCollectionNode currently only supports batch events for tail loads. If you require a head load, consider + * implementing a UIRefreshControl. + */ +- (void)collectionNode:(ASCollectionNode *)collectionNode willBeginBatchFetchWithContext:(ASBatchContext *)context; + +/** + * Tell the collection node if batch fetching should begin. + * + * @param collectionNode The sender. + * + * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of + * objects that can be fetched or no network connection. + * + * If not implemented, the collection node assumes that it should notify its asyncDelegate when batch fetching + * should occur. + */ +- (BOOL)shouldBatchFetchForCollectionNode:(ASCollectionNode *)collectionNode; + +/** + * Provides the constrained size range for measuring the node at the index path. + * + * @param collectionView The sender. + * + * @param indexPath The index path of the node. + * + * @return A constrained size range for layout the node at this index path. + */ +- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Informs the delegate that the collection view will add the given node + * at the given index path to the view hierarchy. + * + * @param collectionView The sender. + * @param node The node that will be displayed. + * @param indexPath The index path of the item that will be displayed. + * + * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + */ +- (void)collectionView:(ASCollectionView *)collectionView willDisplayNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Informs the delegate that the collection view did remove the provided node from the view hierarchy. + * This may be caused by the node scrolling out of view, or by deleting the item + * or its containing section with @c deleteItemsAtIndexPaths: or @c deleteSections: . + * + * @param collectionView The sender. + * @param node The node which was removed from the view hierarchy. + * @param indexPath The index path at which the node was located before it was removed. + * + * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + */ +- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED; + +/** + * Tell the collectionView if batch fetching should begin. + * + * @param collectionView The sender. + * + * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of + * objects that can be fetched or no network connection. + * + * If not implemented, the collectionView assumes that it should notify its asyncDelegate when batch fetching + * should occur. + */ +- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; + +/** + * Informs the delegate that the collection view will add the node + * at the given index path to the view hierarchy. + * + * @param collectionView The sender. + * @param indexPath The index path of the item that will be displayed. + * + * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + * + * This method is deprecated. Use @c collectionView:willDisplayNode:forItemAtIndexPath: instead. + */ +- (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +@end + NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 12aac9f393..64674211bd 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -382,178 +382,18 @@ NS_ASSUME_NONNULL_BEGIN @end - -/** - * This is a node-based UICollectionViewDataSource. - */ -#define ASCollectionViewDataSource ASCollectionDataSource -@protocol ASCollectionDataSource - -@optional - -/** - * Similar to -collectionView:cellForItemAtIndexPath:. - * - * @param collectionView The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a node for display at this indexpath. This will be called on the main thread and should - * not implement reuse (it will be called once per row). Unlike UICollectionView's version, - * this method is not called when the row is about to display. - */ -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Similar to -collectionView:nodeForItemAtIndexPath: - * This method takes precedence over collectionView:nodeForItemAtIndexPath: if implemented. - * - * @param collectionView The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a block that creates the node for display at this indexpath. - * Must be thread-safe (can be called on the main thread or a background - * queue) and should not implement reuse (it will be called once per row). - */ -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Asks the collection view to provide a supplementary node to display in the collection view. - * - * @param collectionView An object representing the collection view requesting this information. - * @param kind The kind of supplementary node to provide. - * @param indexPath The index path that specifies the location of the new supplementary node. - */ -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath; - -/** - * TODO: Docs - */ -- (nullable id)collectionView:(ASCollectionView *)collectionView contextForSection:(NSInteger)section; - -/** - * Indicator to lock the data source for data fetching in async mode. - * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception - * due to the data access in async mode. - * - * @param collectionView The sender. - * @deprecated The data source is always accessed on the main thread, and this method will not be called. - */ -- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; - -/** - * Indicator to unlock the data source for data fetching in async mode. - * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception - * due to the data access in async mode. - * - * @param collectionView The sender. - * @deprecated The data source is always accessed on the main thread, and this method will not be called. - */ -- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; - +ASDISPLAYNODE_DEPRECATED +@protocol ASCollectionViewDataSource @end ASDISPLAYNODE_DEPRECATED @protocol ASCollectionViewDelegate @end -/** - * This is a node-based UICollectionViewDelegate. - */ -@protocol ASCollectionDelegate - -@optional - -/** - * Provides the constrained size range for measuring the node at the index path. - * - * @param collectionView The sender. - * - * @param indexPath The index path of the node. - * - * @return A constrained size range for layout the node at this index path. - */ -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Informs the delegate that the collection view will add the given node - * at the given index path to the view hierarchy. - * - * @param collectionView The sender. - * @param node The node that will be displayed. - * @param indexPath The index path of the item that will be displayed. - * - * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - */ -- (void)collectionView:(ASCollectionView *)collectionView willDisplayNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Informs the delegate that the collection view did remove the provided node from the view hierarchy. - * This may be caused by the node scrolling out of view, or by deleting the item - * or its containing section with @c deleteItemsAtIndexPaths: or @c deleteSections: . - * - * @param collectionView The sender. - * @param node The node which was removed from the view hierarchy. - * @param indexPath The index path at which the node was located before it was removed. - * - * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - */ -- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Receive a message that the collectionView is near the end of its data set and more data should be fetched if - * necessary. - * - * @param collectionView The sender. - * @param context A context object that must be notified when the batch fetch is completed. - * - * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future - * notifications to do batch fetches. This method is called on a background queue. - * - * UICollectionView currently only supports batch events for tail loads. If you require a head load, consider - * implementing a UIRefreshControl. - */ -- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context; - -/** - * Tell the collectionView if batch fetching should begin. - * - * @param collectionView The sender. - * - * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of - * objects that can be fetched or no network connection. - * - * If not implemented, the collectionView assumes that it should notify its asyncDelegate when batch fetching - * should occur. - */ -- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView; - -/** - * Informs the delegate that the collection view will add the node - * at the given index path to the view hierarchy. - * - * @param collectionView The sender. - * @param indexPath The index path of the item that will be displayed. - * - * @warning AsyncDisplayKit processes collection view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - * - * This method is deprecated. Use @c collectionView:willDisplayNode:forItemAtIndexPath: instead. - */ -- (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; - -@end - /** * Defines methods that let you coordinate with a `UICollectionViewFlowLayout` in combination with an `ASCollectionView`. */ -@protocol ASCollectionDelegateFlowLayout +@protocol ASCollectionViewDelegateFlowLayout @optional diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index ba4968a572..6b6f9100db 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -157,37 +157,61 @@ @interface ASCollectionView () )asyncDataSource +- (void)setAsyncDataSource:(id)asyncDataSource { // Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle // the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource @@ -377,18 +401,30 @@ - (void)setAsyncDataSource:(id)asyncDataSource _asyncDataSource = asyncDataSource; _proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; - _asyncDataSourceFlags.asyncDataSourceNodeForItemAtIndexPath = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeForItemAtIndexPath:)]; - _asyncDataSourceFlags.asyncDataSourceNodeBlockForItemAtIndexPath = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeBlockForItemAtIndexPath:)]; - _asyncDataSourceFlags.asyncDataSourceNumberOfSectionsInCollectionView = [_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]; - _asyncDataSourceFlags.asyncDataSourceContextForSection = [_asyncDataSource respondsToSelector:@selector(collectionView:contextForSection:)]; + _asyncDataSourceFlags.collectionViewNodeForItem = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeForItemAtIndexPath:)]; + _asyncDataSourceFlags.collectionViewNodeBlockForItem = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeBlockForItemAtIndexPath:)]; + _asyncDataSourceFlags.numberOfSectionsInCollectionView = [_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]; + _asyncDataSourceFlags.collectionViewNumberOfItemsInSection = [_asyncDataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]; + _asyncDataSourceFlags.collectionViewNodeForSupplementaryElement = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeForSupplementaryElementOfKind:atIndexPath:)]; - ASDisplayNodeAssert(_asyncDataSourceFlags.asyncDataSourceNodeBlockForItemAtIndexPath - || _asyncDataSourceFlags.asyncDataSourceNodeForItemAtIndexPath, @"Data source must implement collectionView:nodeForItemAtIndexPath: or collectionView:nodeBlockForItemAtIndexPath:"); + _asyncDataSourceFlags.collectionNodeNodeForItem = [_asyncDataSource respondsToSelector:@selector(collectionNode:nodeForItemAtIndexPath:)]; + _asyncDataSourceFlags.collectionNodeNodeBlockForItem = [_asyncDataSource respondsToSelector:@selector(collectionNode:nodeBlockForItemAtIndexPath:)]; + _asyncDataSourceFlags.numberOfSectionsInCollectionNode = [_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionNode:)]; + _asyncDataSourceFlags.collectionNodeNumberOfItemsInSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:numberOfItemsInSection:)]; + _asyncDataSourceFlags.collectionNodeContextForSection = [_asyncDataSource respondsToSelector:@selector(collectionNode:contextForSection:)]; + _asyncDataSourceFlags.collectionNodeNodeForSupplementaryElement = [_asyncDataSource respondsToSelector:@selector(collectionNode:nodeForSupplementaryElementOfKind:atIndexPath:)]; + + + ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNumberOfItemsInSection || _asyncDataSourceFlags.collectionViewNumberOfItemsInSection, @"Data source must implement collectionNode:numberOfItemsInSection:"); + ASDisplayNodeAssert(_asyncDataSourceFlags.collectionNodeNodeBlockForItem + || _asyncDataSourceFlags.collectionNodeNodeForItem + || _asyncDataSourceFlags.collectionViewNodeBlockForItem + || _asyncDataSourceFlags.collectionViewNodeForItem, @"Data source must implement collectionNode:nodeBlockForItemAtIndexPath: or collectionNode:nodeForItemAtIndexPath:"); } super.dataSource = (id)_proxyDataSource; - if (_layoutInspectorFlags.layoutInspectorDidChangeCollectionViewDataSource) { + if (_layoutInspectorFlags.didChangeCollectionViewDataSource) { [self.layoutInspector didChangeCollectionViewDataSource:asyncDataSource]; } } @@ -410,32 +446,46 @@ - (void)setAsyncDelegate:(id)asyncDelegate _asyncDelegate = asyncDelegate; _proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; - _asyncDelegateFlags.asyncDelegateScrollViewDidScroll = [_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)]; - _asyncDelegateFlags.asyncDelegateScrollViewWillEndDraggingWithVelocityTargetContentOffset = [_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewWillDisplayNodeForItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNode:forItemAtIndexPath:)]; - if (_asyncDelegateFlags.asyncDelegateCollectionViewWillDisplayNodeForItemAtIndexPath == NO) { - _asyncDelegateFlags.asyncDelegateCollectionViewWillDisplayNodeForItemAtIndexPathDeprecated = [_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNodeForItemAtIndexPath:)]; + _asyncDelegateFlags.scrollViewDidScroll = [_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)]; + _asyncDelegateFlags.scrollViewWillEndDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]; + _asyncDelegateFlags.scrollViewWillBeginDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]; + _asyncDelegateFlags.scrollViewDidEndDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]; + _asyncDelegateFlags.collectionViewWillDisplayNodeForItem = [_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNode:forItemAtIndexPath:)]; + if (_asyncDelegateFlags.collectionViewWillDisplayNodeForItem == NO) { + _asyncDelegateFlags.collectionViewWillDisplayNodeForItemDeprecated = [_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNodeForItemAtIndexPath:)]; } - _asyncDelegateFlags.asyncDelegateCollectionViewDidEndDisplayingNodeForItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNode:forItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewWillBeginBatchFetchWithContext = [_asyncDelegate respondsToSelector:@selector(collectionView:willBeginBatchFetchWithContext:)]; - _asyncDelegateFlags.asyncDelegateShouldBatchFetchForCollectionView = [_asyncDelegate respondsToSelector:@selector(shouldBatchFetchForCollectionView:)]; - _asyncDelegateFlags.asyncDelegateScrollViewWillBeginDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]; - _asyncDelegateFlags.asyncDelegateScrollViewDidEndDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewShouldSelectItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldSelectItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewDidSelectItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewShouldDeselectItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldDeselectItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewDidDeselectItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didDeselectItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewShouldHighlightItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldHighlightItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewDidHighlightItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didHighlightItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewDidUnhighlightItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didUnhighlightItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewShouldShowMenuForItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldShowMenuForItemAtIndexPath:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewCanPerformActionForItemAtIndexPathWithSender = [_asyncDelegate respondsToSelector:@selector(collectionView:canPerformAction:forItemAtIndexPath:withSender:)]; - _asyncDelegateFlags.asyncDelegateCollectionViewPerformActionForItemAtIndexPathWithSender = [_asyncDelegate respondsToSelector:@selector(collectionView:performAction:forItemAtIndexPath:withSender:)]; + _asyncDelegateFlags.collectionViewDidEndDisplayingNodeForItem = [_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNode:forItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewWillBeginBatchFetch = [_asyncDelegate respondsToSelector:@selector(collectionView:willBeginBatchFetchWithContext:)]; + _asyncDelegateFlags.shouldBatchFetchForCollectionView = [_asyncDelegate respondsToSelector:@selector(shouldBatchFetchForCollectionView:)]; + _asyncDelegateFlags.collectionViewShouldSelectItem = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldSelectItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewDidSelectItem = [_asyncDelegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewShouldDeselectItem = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldDeselectItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewDidDeselectItem = [_asyncDelegate respondsToSelector:@selector(collectionView:didDeselectItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewShouldHighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldHighlightItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewDidHighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionView:didHighlightItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewDidUnhighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionView:didUnhighlightItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewShouldShowMenuForItem = [_asyncDelegate respondsToSelector:@selector(collectionView:shouldShowMenuForItemAtIndexPath:)]; + _asyncDelegateFlags.collectionViewCanPerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionView:canPerformAction:forItemAtIndexPath:withSender:)]; + _asyncDelegateFlags.collectionViewPerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionView:performAction:forItemAtIndexPath:withSender:)]; + _asyncDelegateFlags.collectionNodeWillDisplayItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:willDisplayItemWithNode:)]; + _asyncDelegateFlags.collectionNodeDidEndDisplayingItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:didEndDisplayingItemWithNode:)]; + _asyncDelegateFlags.collectionNodeWillBeginBatchFetch = [_asyncDelegate respondsToSelector:@selector(collectionNode:willBeginBatchFetchWithContext:)]; + _asyncDelegateFlags.shouldBatchFetchForCollectionNode = [_asyncDelegate respondsToSelector:@selector(shouldBatchFetchForCollectionNode:)]; + _asyncDelegateFlags.collectionNodeShouldSelectItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldSelectItemWithNode:)]; + _asyncDelegateFlags.collectionNodeDidSelectItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:didSelectItemWithNode:)]; + _asyncDelegateFlags.collectionNodeShouldDeselectItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldDeselectItemWithNode:)]; + _asyncDelegateFlags.collectionNodeDidDeselectItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:didDeselectItemWithNode:)]; + _asyncDelegateFlags.collectionNodeShouldHighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldHighlightItemWithNode:)]; + _asyncDelegateFlags.collectionNodeDidHighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:didHighlightItemWithNode:)]; + _asyncDelegateFlags.collectionNodeDidUnhighlightItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:didUnhighlightItemWithNode:)]; + _asyncDelegateFlags.collectionNodeShouldShowMenuForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:shouldShowMenuForItemWithNode:)]; + _asyncDelegateFlags.collectionNodeCanPerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:canPerformAction:forItemWithNode:sender:)]; + _asyncDelegateFlags.collectionNodePerformActionForItem = [_asyncDelegate respondsToSelector:@selector(collectionNode:performAction:forItemWithNode:sender:)]; } super.delegate = (id)_proxyDelegate; - if (_layoutInspectorFlags.layoutInspectorDidChangeCollectionViewDelegate) { + if (_layoutInspectorFlags.didChangeCollectionViewDelegate) { [self.layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; } } @@ -474,8 +524,8 @@ - (void)setLayoutInspector:(id)layoutInspector { _layoutInspector = layoutInspector; - _layoutInspectorFlags.layoutInspectorDidChangeCollectionViewDataSource = [_layoutInspector respondsToSelector:@selector(didChangeCollectionViewDataSource:)]; - _layoutInspectorFlags.layoutInspectorDidChangeCollectionViewDelegate = [_layoutInspector respondsToSelector:@selector(didChangeCollectionViewDelegate:)]; + _layoutInspectorFlags.didChangeCollectionViewDataSource = [_layoutInspector respondsToSelector:@selector(didChangeCollectionViewDataSource:)]; + _layoutInspectorFlags.didChangeCollectionViewDelegate = [_layoutInspector respondsToSelector:@selector(didChangeCollectionViewDelegate:)]; } - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType @@ -766,11 +816,13 @@ - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(_ASCo ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with cell that will be displayed not to be nil. indexPath: %@", indexPath); - if (_asyncDelegateFlags.asyncDelegateCollectionViewWillDisplayNodeForItemAtIndexPath) { - [_asyncDelegate collectionView:self willDisplayNode:cellNode forItemAtIndexPath:indexPath]; + if (_asyncDelegateFlags.collectionNodeWillDisplayItem) { + [_asyncDelegate collectionNode:self.collectionNode willDisplayItemWithNode:cellNode]; + } else if (_asyncDelegateFlags.collectionViewWillDisplayNodeForItem) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - } else if (_asyncDelegateFlags.asyncDelegateCollectionViewWillDisplayNodeForItemAtIndexPathDeprecated) { + [_asyncDelegate collectionView:self willDisplayNode:cellNode forItemAtIndexPath:indexPath]; + } else if (_asyncDelegateFlags.collectionViewWillDisplayNodeForItemDeprecated) { [_asyncDelegate collectionView:self willDisplayNodeForItemAtIndexPath:indexPath]; } #pragma clang diagnostic pop @@ -787,9 +839,13 @@ - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:( ASCellNode *cellNode = [cell node]; ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with removed cell not to be nil."); - if (_asyncDelegateFlags.asyncDelegateCollectionViewDidEndDisplayingNodeForItemAtIndexPath) { - ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with removed cell not to be nil."); + if (_asyncDelegateFlags.collectionNodeDidEndDisplayingItem) { + [_asyncDelegate collectionNode:self.collectionNode didEndDisplayingItemWithNode:cellNode]; + } else if (_asyncDelegateFlags.collectionViewDidEndDisplayingNodeForItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self didEndDisplayingNode:cellNode forItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } [_rangeController setNeedsUpdate]; @@ -800,11 +856,34 @@ - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:( cell.layoutAttributes = nil; } +- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath +{ + if (_asyncDelegateFlags.collectionNodeWillDisplaySupplementaryElement) { + ASCellNode *node = [self supplementaryNodeForElementKind:elementKind atIndexPath:indexPath]; + ASDisplayNodeAssert([node.supplementaryElementKind isEqualToString:elementKind], @"Expected node for supplementary element to have kind '%@', got '%@'.", elementKind, node.supplementaryElementKind); + [_asyncDelegate collectionNode:self.collectionNode willDisplaySupplementaryElementWithNode:node]; + } +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath +{ + if (_asyncDelegateFlags.collectionNodeDidEndDisplayingSupplementaryElement) { + ASCellNode *node = [self supplementaryNodeForElementKind:elementKind atIndexPath:indexPath]; + ASDisplayNodeAssert([node.supplementaryElementKind isEqualToString:elementKind], @"Expected node for supplementary element to have kind '%@', got '%@'.", elementKind, node.supplementaryElementKind); + [_asyncDelegate collectionNode:self.collectionNode didEndDisplayingSupplementaryElementWithNode:node]; + } +} + - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewShouldSelectItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeShouldSelectItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode shouldSelectItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewShouldSelectItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate collectionView:self shouldSelectItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { return YES; } @@ -812,17 +891,27 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtInde - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewDidSelectItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeDidSelectItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + [_asyncDelegate collectionNode:self.collectionNode didSelectItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewDidSelectItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self didSelectItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } } - (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewShouldDeselectItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeShouldDeselectItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode shouldDeselectItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewShouldDeselectItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate collectionView:self shouldDeselectItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { return YES; } @@ -830,17 +919,27 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIn - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewDidSelectItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeDidSelectItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode didSelectItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewDidSelectItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self didDeselectItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } } - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewShouldHighlightItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeShouldHighlightItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode shouldHighlightItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewShouldHighlightItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate collectionView:self shouldHighlightItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { return YES; } @@ -848,25 +947,40 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtI - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewDidHighlightItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeDidHighlightItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + [_asyncDelegate collectionNode:self.collectionNode didHighlightItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewDidHighlightItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self didHighlightItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } } - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewDidUnhighlightItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeDidUnhighlightItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + [_asyncDelegate collectionNode:self.collectionNode didUnhighlightItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewDidUnhighlightItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self didUnhighlightItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } } - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - if (_asyncDelegateFlags.asyncDelegateCollectionViewShouldShowMenuForItemAtIndexPath) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeShouldShowMenuForItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode shouldShowMenuForItemWithNode:node]; + } else if (_asyncDelegateFlags.collectionViewShouldShowMenuForItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate collectionView:self shouldShowMenuForItemAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { return NO; } @@ -874,9 +988,14 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemA - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(nonnull SEL)action forItemAtIndexPath:(nonnull NSIndexPath *)indexPath withSender:(nullable id)sender { - if (_asyncDelegateFlags.asyncDelegateCollectionViewCanPerformActionForItemAtIndexPathWithSender) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodeCanPerformActionForItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_asyncDelegate collectionNode:self.collectionNode canPerformAction:action forItemWithNode:node sender:sender]; + } else if (_asyncDelegateFlags.collectionViewCanPerformActionForItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate collectionView:self canPerformAction:action forItemAtIndexPath:indexPath withSender:sender]; +#pragma clang diagnostic pop } else { return NO; } @@ -884,9 +1003,14 @@ - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(nonn - (void)collectionView:(UICollectionView *)collectionView performAction:(nonnull SEL)action forItemAtIndexPath:(nonnull NSIndexPath *)indexPath withSender:(nullable id)sender { - if (_asyncDelegateFlags.asyncDelegateCollectionViewPerformActionForItemAtIndexPathWithSender) { - indexPath = [self convertIndexPathToCollectionNode:indexPath]; + if (_asyncDelegateFlags.collectionNodePerformActionForItem) { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + [_asyncDelegate collectionNode:self.collectionNode performAction:action forItemWithNode:node sender:sender]; + } else if (_asyncDelegateFlags.collectionViewPerformActionForItem) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [_asyncDelegate collectionView:self performAction:action forItemAtIndexPath:indexPath withSender:sender]; +#pragma clang diagnostic pop } } @@ -904,7 +1028,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView inScrollView:scrollView withCellFrame:collectionCell.frame]; } - if (_asyncDelegateFlags.asyncDelegateScrollViewDidScroll) { + if (_asyncDelegateFlags.scrollViewDidScroll) { [_asyncDelegate scrollViewDidScroll:scrollView]; } } @@ -922,7 +1046,7 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi [self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollDirection] contentOffset:*targetContentOffset]; } - if (_asyncDelegateFlags.asyncDelegateScrollViewWillEndDraggingWithVelocityTargetContentOffset) { + if (_asyncDelegateFlags.scrollViewWillEndDragging) { [_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:(targetContentOffset ? : &contentOffset)]; } } @@ -934,7 +1058,7 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView inScrollView:scrollView withCellFrame:collectionCell.frame]; } - if (_asyncDelegateFlags.asyncDelegateScrollViewWillBeginDragging) { + if (_asyncDelegateFlags.scrollViewWillBeginDragging) { [_asyncDelegate scrollViewWillBeginDragging:scrollView]; } } @@ -946,7 +1070,7 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL inScrollView:scrollView withCellFrame:collectionCell.frame]; } - if (_asyncDelegateFlags.asyncDelegateScrollViewDidEndDragging) { + if (_asyncDelegateFlags.scrollViewDidEndDragging) { [_asyncDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; } } @@ -1061,9 +1185,14 @@ - (ASBatchContext *)batchContext - (BOOL)canBatchFetch { // if the delegate does not respond to this method, there is no point in starting to fetch - BOOL canFetch = _asyncDelegateFlags.asyncDelegateCollectionViewWillBeginBatchFetchWithContext; - if (canFetch && _asyncDelegateFlags.asyncDelegateShouldBatchFetchForCollectionView) { + BOOL canFetch = _asyncDelegateFlags.collectionNodeWillBeginBatchFetch || _asyncDelegateFlags.collectionViewWillBeginBatchFetch; + if (canFetch && _asyncDelegateFlags.shouldBatchFetchForCollectionNode) { + return [_asyncDelegate shouldBatchFetchForCollectionNode:self.collectionNode]; + } else if (canFetch && _asyncDelegateFlags.shouldBatchFetchForCollectionView) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [_asyncDelegate shouldBatchFetchForCollectionView:self]; +#pragma clang diagnostic pop } else { return canFetch; } @@ -1102,9 +1231,12 @@ - (void)_beginBatchFetchingIfNeededWithScrollView:(UIScrollView context = nil; - if (_asyncDataSourceFlags.asyncDataSourceContextForSection) { - context = [_asyncDataSource collectionView:self contextForSection:section]; + if (_asyncDataSourceFlags.collectionNodeContextForSection) { + context = [_asyncDataSource collectionNode:self.collectionNode contextForSection:section]; } if (context != nil) { @@ -1556,16 +1731,6 @@ - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(N ASDisplayNodeAssert(![self.asyncDataSource respondsToSelector:_cmd], @"%@ is not supported by ASCollectionView - please remove or disable this data source method.", NSStringFromSelector(_cmd)); } -- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath -{ - ASDisplayNodeAssert(![self.asyncDataSource respondsToSelector:_cmd], @"%@ is not supported by ASCollectionView - please remove or disable this delegate method.", NSStringFromSelector(_cmd)); -} - -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath -{ - ASDisplayNodeAssert(![self.asyncDataSource respondsToSelector:_cmd], @"%@ is not supported by ASCollectionView - please remove or disable this delegate method.", NSStringFromSelector(_cmd)); -} - #endif @end diff --git a/AsyncDisplayKit/ASCollectionViewProtocols.h b/AsyncDisplayKit/ASCollectionViewProtocols.h index ea82ddae5d..86fff2e37a 100644 --- a/AsyncDisplayKit/ASCollectionViewProtocols.h +++ b/AsyncDisplayKit/ASCollectionViewProtocols.h @@ -13,19 +13,19 @@ NS_ASSUME_NONNULL_BEGIN /** * This is a subset of UICollectionViewDataSource. * - * @see ASCollectionViewDataSource + * @see ASCollectionDataSource */ -@protocol ASCommonCollectionViewDataSource +@protocol ASCommonCollectionDataSource @required -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section; +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED; @optional -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView; +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; -- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath; +- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; @end @@ -35,27 +35,27 @@ NS_ASSUME_NONNULL_BEGIN * * @see ASCollectionDelegate */ -@protocol ASCommonCollectionViewDelegate +@protocol ASCommonCollectionDelegate @optional - (UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout; -- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath; +- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath; -- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath; -- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath; -- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; -- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; @end diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 63db4ae6ac..909d1089dc 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -16,7 +16,7 @@ #import "ASPagerFlowLayout.h" #import "ASCollectionView+Undeprecated.h" -@interface ASPagerNode () +@interface ASPagerNode () { ASPagerFlowLayout *_flowLayout; @@ -64,7 +64,7 @@ - (void)didLoad [super didLoad]; ASCollectionView *cv = self.view; - cv.asyncDataSource = (id)_proxyDataSource ?: self; + cv.asyncDataSource = (id)_proxyDataSource ?: self; cv.asyncDelegate = (id)_proxyDelegate ?: self; #if TARGET_OS_IOS cv.pagingEnabled = YES; @@ -110,7 +110,7 @@ - (ASCellNode *)nodeForPageAtIndex:(NSInteger)index return [self.view nodeForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; } -#pragma mark - ASCollectionViewDataSource +#pragma mark - ASCollectionDataSource - (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 464c0aaa1f..63ee9d7811 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -295,4 +295,244 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * This is a node-based UITableViewDataSource. + */ +@protocol ASTableDataSource + +@optional + +/** + * Similar to -tableView:cellForRowAtIndexPath:. + * + * @param tableNode The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UITableView's version, this method + * is not called when the row is about to display. + */ +- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; + +- (NSInteger)numberOfSectionsInTableNode:(ASTableNode *)tableNode; + +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section; + +/** + * Similar to -tableView:nodeForRowAtIndexPath: + * This method takes precedence over tableNode:nodeForRowAtIndexPath: if implemented. + * @param tableNode The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a block that creates the node for display at this indexpath. + * Must be thread-safe (can be called on the main thread or a background + * queue) and should not implement reuse (it will be called once per row). + */ + +- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; + +/** + * Similar to -tableView:cellForRowAtIndexPath:. + * + * @param tableNode The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UITableView's version, this method + * is not called when the row is about to display. + */ +- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + + +/** + * Similar to -tableView:nodeForRowAtIndexPath: + * This method takes precedence over tableView:nodeForRowAtIndexPath: if implemented. + * @param tableView The sender. + * + * @param indexPath The index path of the requested node. + * + * @return a block that creates the node for display at this indexpath. + * Must be thread-safe (can be called on the main thread or a background + * queue) and should not implement reuse (it will be called once per row). + */ + +- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + +/** + * Indicator to lock the data source for data fetching in async mode. + * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception + * due to the data access in async mode. + * + * @param tableView The sender. + * @deprecated The data source is always accessed on the main thread, and this method will not be called. + */ +- (void)tableViewLockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; + +/** + * Indicator to unlock the data source for data fetching in asyn mode. + * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception + * due to the data access in async mode. + * + * @param tableView The sender. + * @deprecated The data source is always accessed on the main thread, and this method will not be called. + */ +- (void)tableViewUnlockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; + +@end + +/** + * This is a node-based UITableViewDelegate. + * + * Note that -tableView:heightForRowAtIndexPath: has been removed; instead, your custom ASCellNode subclasses are + * responsible for deciding their preferred onscreen height in -calculateSizeThatFits:. + */ +@protocol ASTableDelegate + +@optional + +- (void)tableNode:(ASTableNode *)tableNode willDisplayRowWithNode:(ASCellNode *)node; + +- (void)tableNode:(ASTableNode *)tableNode didEndDisplayingRowWithNode:(ASCellNode *)node; + +- (nullable ASCellNode *)tableNode:(ASTableNode *)tableNode willSelectRowWithNode:(ASCellNode *)node; + +- (void)tableNode:(ASTableNode *)tableNode didSelectRowWithNode:(ASCellNode *)node; + +- (nullable ASCellNode *)tableNode:(ASTableNode *)tableNode willDeselectRowWithNode:(ASCellNode *)node; + +- (void)tableNode:(ASTableNode *)tableNode didDeselectRowWithNode:(ASCellNode *)node; + +- (BOOL)tableNode:(ASTableNode *)tableNode shouldHighlightRowWithNode:(ASCellNode *)node; +- (void)tableNode:(ASTableNode *)tableNode didHighlightRowWithNode:(ASCellNode *)node; +- (void)tableNode:(ASTableNode *)tableNode didUnhighlightRowWithNode:(ASCellNode *)node; + +- (BOOL)tableNode:(ASTableNode *)tableNode shouldShowMenuForRowWithNode:(ASCellNode *)node; +- (BOOL)tableNode:(ASTableNode *)tableNode canPerformAction:(SEL)action forRowWithNode:(ASCellNode *)node withSender:(nullable id)sender; +- (void)tableNode:(ASTableNode *)tableNode performAction:(SEL)action forRowWithNode:(ASCellNode *)node withSender:(nullable id)sender; + +/** + * Provides the constrained size range for measuring the row at the index path. + * Note: the widths in the returned size range are ignored! + * + * @param tableNode The sender. + * + * @param indexPath The index path of the node. + * + * @return A constrained size range for layout the node at this index path. + */ +- (ASSizeRange)tableNode:(ASTableNode *)tableNode constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. + * + * @param tableView The sender. + * @param context A context object that must be notified when the batch fetch is completed. + * + * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future + * notifications to do batch fetches. This method is called on a background queue. + * + * ASTableView currently only supports batch events for tail loads. If you require a head load, consider implementing a + * UIRefreshControl. + */ +- (void)tableNode:(ASTableNode *)tableNode willBeginBatchFetchWithContext:(ASBatchContext *)context; + +/** + * Tell the tableView if batch fetching should begin. + * + * @param tableView The sender. + * + * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of + * objects that can be fetched or no network connection. + * + * If not implemented, the tableView assumes that it should notify its asyncDelegate when batch fetching + * should occur. + */ +- (BOOL)shouldBatchFetchForTableNode:(ASTableNode *)tableNode; + +/** + * Informs the delegate that the table view will add the given node + * at the given index path to the view hierarchy. + * + * @param tableView The sender. + * @param node The node that will be displayed. + * @param indexPath The index path of the row that will be displayed. + * + * @warning AsyncDisplayKit processes table view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + */ +- (void)tableView:(ASTableView *)tableView willDisplayNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Informs the delegate that the table view did remove the provided node from the view hierarchy. + * This may be caused by the node scrolling out of view, or by deleting the row + * or its containing section with @c deleteRowsAtIndexPaths:withRowAnimation: or @c deleteSections:withRowAnimation: . + * + * @param tableView The sender. + * @param node The node which was removed from the view hierarchy. + * @param indexPath The index path at which the node was located before the removal. + * + * @warning AsyncDisplayKit processes table view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + */ +- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +/** + * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. + * + * @param tableView The sender. + * @param context A context object that must be notified when the batch fetch is completed. + * + * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future + * notifications to do batch fetches. This method is called on a background queue. + * + * ASTableView currently only supports batch events for tail loads. If you require a head load, consider implementing a + * UIRefreshControl. + */ +- (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED; + +/** + * Tell the tableView if batch fetching should begin. + * + * @param tableView The sender. + * + * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of + * objects that can be fetched or no network connection. + * + * If not implemented, the tableView assumes that it should notify its asyncDelegate when batch fetching + * should occur. + */ +- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + +/** + * Provides the constrained size range for measuring the row at the index path. + * Note: the widths in the returned size range are ignored! + * + * @param tableView The sender. + * + * @param indexPath The index path of the node. + * + * @return A constrained size range for layout the node at this index path. + */ +- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + +/** + * Informs the delegate that the table view will add the node + * at the given index path to the view hierarchy. + * + * @param tableView The sender. + * @param indexPath The index path of the row that will be displayed. + * + * @warning AsyncDisplayKit processes table view edits asynchronously. The index path + * passed into this method may not correspond to the same item in your data source + * if your data source has been updated since the last edit was processed. + * + * This method is deprecated. Use @c tableView:willDisplayNode:forRowAtIndexPath: instead. + */ +- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; + +@end + NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index aea30c42b5..a74ba66936 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -311,250 +311,10 @@ NS_ASSUME_NONNULL_BEGIN @end -/** - * This is a node-based UITableViewDataSource. - */ -@protocol ASTableDataSource - -@optional - -/** - * Similar to -tableView:cellForRowAtIndexPath:. - * - * @param tableNode The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UITableView's version, this method - * is not called when the row is about to display. - */ -- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; - -- (NSInteger)numberOfSectionsInTableNode:(ASTableNode *)tableNode; - -- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section; - -/** - * Similar to -tableView:nodeForRowAtIndexPath: - * This method takes precedence over tableNode:nodeForRowAtIndexPath: if implemented. - * @param tableNode The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a block that creates the node for display at this indexpath. - * Must be thread-safe (can be called on the main thread or a background - * queue) and should not implement reuse (it will be called once per row). - */ - -- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; - -/** - * Similar to -tableView:cellForRowAtIndexPath:. - * - * @param tableNode The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UITableView's version, this method - * is not called when the row is about to display. - */ -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; - - -/** - * Similar to -tableView:nodeForRowAtIndexPath: - * This method takes precedence over tableView:nodeForRowAtIndexPath: if implemented. - * @param tableView The sender. - * - * @param indexPath The index path of the requested node. - * - * @return a block that creates the node for display at this indexpath. - * Must be thread-safe (can be called on the main thread or a background - * queue) and should not implement reuse (it will be called once per row). - */ - -- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; - -/** - * Indicator to lock the data source for data fetching in async mode. - * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception - * due to the data access in async mode. - * - * @param tableView The sender. - * @deprecated The data source is always accessed on the main thread, and this method will not be called. - */ -- (void)tableViewLockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; - -/** - * Indicator to unlock the data source for data fetching in asyn mode. - * We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception - * due to the data access in async mode. - * - * @param tableView The sender. - * @deprecated The data source is always accessed on the main thread, and this method will not be called. - */ -- (void)tableViewUnlockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; - -@end - ASDISPLAYNODE_DEPRECATED @protocol ASTableViewDataSource @end -/** - * This is a node-based UITableViewDelegate. - * - * Note that -tableView:heightForRowAtIndexPath: has been removed; instead, your custom ASCellNode subclasses are - * responsible for deciding their preferred onscreen height in -calculateSizeThatFits:. - */ -@protocol ASTableDelegate - -@optional - -- (void)tableNode:(ASTableNode *)tableNode willDisplayRowWithNode:(ASCellNode *)node; - -- (void)tableNode:(ASTableNode *)tableNode didEndDisplayingRowWithNode:(ASCellNode *)node; - -- (nullable ASCellNode *)tableNode:(ASTableNode *)tableNode willSelectRowWithNode:(ASCellNode *)node; - -- (void)tableNode:(ASTableNode *)tableNode didSelectRowWithNode:(ASCellNode *)node; - -- (nullable ASCellNode *)tableNode:(ASTableNode *)tableNode willDeselectRowWithNode:(ASCellNode *)node; - -- (void)tableNode:(ASTableNode *)tableNode didDeselectRowWithNode:(ASCellNode *)node; - -- (BOOL)tableNode:(ASTableNode *)tableNode shouldHighlightRowWithNode:(ASCellNode *)node; -- (void)tableNode:(ASTableNode *)tableNode didHighlightRowWithNode:(ASCellNode *)node; -- (void)tableNode:(ASTableNode *)tableNode didUnhighlightRowWithNode:(ASCellNode *)node; - -- (BOOL)tableNode:(ASTableNode *)tableNode shouldShowMenuForRowWithNode:(ASCellNode *)node; -- (BOOL)tableNode:(ASTableNode *)tableNode canPerformAction:(SEL)action forRowWithNode:(ASCellNode *)node withSender:(nullable id)sender; -- (void)tableNode:(ASTableNode *)tableNode performAction:(SEL)action forRowWithNode:(ASCellNode *)node withSender:(nullable id)sender; - -/** - * Provides the constrained size range for measuring the row at the index path. - * Note: the widths in the returned size range are ignored! - * - * @param tableNode The sender. - * - * @param indexPath The index path of the node. - * - * @return A constrained size range for layout the node at this index path. - */ -- (ASSizeRange)tableNode:(ASTableNode *)tableNode constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. - * - * @param tableView The sender. - * @param context A context object that must be notified when the batch fetch is completed. - * - * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future - * notifications to do batch fetches. This method is called on a background queue. - * - * ASTableView currently only supports batch events for tail loads. If you require a head load, consider implementing a - * UIRefreshControl. - */ -- (void)tableNode:(ASTableNode *)tableNode willBeginBatchFetchWithContext:(ASBatchContext *)context; - -/** - * Tell the tableView if batch fetching should begin. - * - * @param tableView The sender. - * - * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of - * objects that can be fetched or no network connection. - * - * If not implemented, the tableView assumes that it should notify its asyncDelegate when batch fetching - * should occur. - */ -- (BOOL)shouldBatchFetchForTableNode:(ASTableNode *)tableNode; - -/** - * Informs the delegate that the table view will add the given node - * at the given index path to the view hierarchy. - * - * @param tableView The sender. - * @param node The node that will be displayed. - * @param indexPath The index path of the row that will be displayed. - * - * @warning AsyncDisplayKit processes table view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - */ -- (void)tableView:(ASTableView *)tableView willDisplayNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; - -/** - * Informs the delegate that the table view did remove the provided node from the view hierarchy. - * This may be caused by the node scrolling out of view, or by deleting the row - * or its containing section with @c deleteRowsAtIndexPaths:withRowAnimation: or @c deleteSections:withRowAnimation: . - * - * @param tableView The sender. - * @param node The node which was removed from the view hierarchy. - * @param indexPath The index path at which the node was located before the removal. - * - * @warning AsyncDisplayKit processes table view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - */ -- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; - -/** - * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. - * - * @param tableView The sender. - * @param context A context object that must be notified when the batch fetch is completed. - * - * @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future - * notifications to do batch fetches. This method is called on a background queue. - * - * ASTableView currently only supports batch events for tail loads. If you require a head load, consider implementing a - * UIRefreshControl. - */ -- (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED; - -/** - * Tell the tableView if batch fetching should begin. - * - * @param tableView The sender. - * - * @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of - * objects that can be fetched or no network connection. - * - * If not implemented, the tableView assumes that it should notify its asyncDelegate when batch fetching - * should occur. - */ -- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; - -/** - * Provides the constrained size range for measuring the row at the index path. - * Note: the widths in the returned size range are ignored! - * - * @param tableView The sender. - * - * @param indexPath The index path of the node. - * - * @return A constrained size range for layout the node at this index path. - */ -- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; - -/** - * Informs the delegate that the table view will add the node - * at the given index path to the view hierarchy. - * - * @param tableView The sender. - * @param indexPath The index path of the row that will be displayed. - * - * @warning AsyncDisplayKit processes table view edits asynchronously. The index path - * passed into this method may not correspond to the same item in your data source - * if your data source has been updated since the last edit was processed. - * - * This method is deprecated. Use @c tableView:willDisplayNode:forRowAtIndexPath: instead. - */ -- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; - -@end - ASDISPLAYNODE_DEPRECATED @protocol ASTableViewDelegate @end diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index 2b9de76b45..70009307a3 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -63,7 +63,11 @@ - (void)didChangeCollectionViewDelegate:(id)delegate - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath { if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { + // TODO: Handle collection node +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { // With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDelegate."); @@ -146,7 +150,10 @@ - (void)didChangeCollectionViewDataSource:(id)dataSource - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath { if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; +#pragma clang diagnostic pop } else { // With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDelegate."); @@ -213,9 +220,9 @@ - (CGFloat)usedLayoutValueForSize:(CGSize)size } } -- (id)delegateForCollectionView:(ASCollectionView *)collectionView +- (id)delegateForCollectionView:(ASCollectionView *)collectionView { - return (id)collectionView.asyncDelegate; + return (id)collectionView.asyncDelegate; } @end diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index 3fb0602d51..460c50f0b6 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -9,8 +9,8 @@ // #import "ASDelegateProxy.h" -#import "ASTableView.h" -#import "ASCollectionView.h" +#import "ASTableNode.h" +#import "ASCollectionNode.h" #import "ASAssert.h" @implementation ASTableViewProxy @@ -82,13 +82,15 @@ - (BOOL)interceptsSelector:(SEL)selector selector == @selector(collectionView:canPerformAction:forItemAtIndexPath:withSender:) || selector == @selector(collectionView:performAction:forItemAtIndexPath:withSender:) || - // handled by ASRangeController + // Item counts selector == @selector(numberOfSectionsInCollectionView:) || selector == @selector(collectionView:numberOfItemsInSection:) || - // used for ASRangeController visibility updates + // Element appearance callbacks selector == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || selector == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || + selector == @selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:) || + selector == @selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:) || // used for batch fetching API selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) || @@ -102,9 +104,7 @@ - (BOOL)interceptsSelector:(SEL)selector // intercepted due to not being supported by ASCollectionView (prevent bugs caused by usage) selector == @selector(collectionView:canMoveItemAtIndexPath:) || - selector == @selector(collectionView:moveItemAtIndexPath:toIndexPath:) || - selector == @selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:) || - selector == @selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:) + selector == @selector(collectionView:moveItemAtIndexPath:toIndexPath:) ); } diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index 2ec3210c8e..f4c7e229a1 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -13,6 +13,7 @@ #import #import "ASCollectionView.h" +#import "ASCollectionNode.h" #import "ASCollectionViewFlowLayoutInspector.h" #import "ASCellNode.h" @@ -25,7 +26,7 @@ - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionVi /** * Test Data Source */ -@interface InspectorTestDataSource : NSObject +@interface InspectorTestDataSource : NSObject @end @implementation InspectorTestDataSource @@ -80,7 +81,7 @@ @interface ASCollectionViewFlowLayoutInspectorTests : XCTestCase /** * Test Delegate for Header Reference Size Implementation */ -@interface HeaderReferenceSizeTestDelegate : NSObject +@interface HeaderReferenceSizeTestDelegate : NSObject @end @@ -96,7 +97,7 @@ - (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollection /** * Test Delegate for Footer Reference Size Implementation */ -@interface FooterReferenceSizeTestDelegate : NSObject +@interface FooterReferenceSizeTestDelegate : NSObject @end diff --git a/AsyncDisplayKitTests/ASCollectionViewTests.mm b/AsyncDisplayKitTests/ASCollectionViewTests.mm index 61ed889f95..555588a394 100644 --- a/AsyncDisplayKitTests/ASCollectionViewTests.mm +++ b/AsyncDisplayKitTests/ASCollectionViewTests.mm @@ -55,7 +55,7 @@ @implementation ASTestSectionContext @end -@interface ASCollectionViewTestDelegate : NSObject +@interface ASCollectionViewTestDelegate : NSObject @property (nonatomic, assign) NSInteger sectionGeneration; @@ -111,7 +111,7 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSe return _itemCounts[section]; } -- (id)collectionView:(ASCollectionView *)collectionView contextForSection:(NSInteger)section +- (id)collectionNode:(ASCollectionNode *)collectionNode contextForSection:(NSInteger)section { ASTestSectionContext *context = [[ASTestSectionContext alloc] init]; context.sectionGeneration = _sectionGeneration; @@ -452,7 +452,8 @@ - (void)testThatDisappearingSupplementariesWithLayerBackedNodesDontFailAssert { UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UICollectionViewLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *cv = [[ASCollectionView alloc] initWithFrame:window.bounds collectionViewLayout:layout]; + ASCollectionNode *cn = [[ASCollectionNode alloc] initWithFrame:window.bounds collectionViewLayout:layout]; + ASCollectionView *cv = cn.view; __unused NSMutableSet *keepaliveNodes = [NSMutableSet set]; @@ -469,7 +470,7 @@ - (void)testThatDisappearingSupplementariesWithLayerBackedNodesDontFailAssert layerBacked.name = [NSString stringWithFormat:@"Subnode #%d", thisNodeIdx]; [suppNode addSubnode:layerBacked]; [invocation setReturnValue:&suppNode]; - }] collectionView:cv nodeForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:OCMOCK_ANY]; + }] collectionNode:cn nodeForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:OCMOCK_ANY]; [[[dataSource stub] andReturnValue:[NSNumber numberWithInteger:1]] numberOfSectionsInCollectionView:cv]; cv.asyncDataSource = dataSource;