Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

[ASCollectionView] Separate indexPath Spaces More Clearly #2348

Closed
wants to merge 9 commits into from

Conversation

Adlai-Holler
Copy link
Contributor

@Adlai-Holler Adlai-Holler commented Oct 5, 2016

Users are getting confused when we tell them "the index paths are out-of-sync" or "don't line up."

To help tackle this major problem, this diff:

  • Add failing unit tests for the new behavior.
  • Makes nodeAtIndexPath and indexPathForNode work in the data source's index space, not in the UIKit index space. So immediately after submitting an update, if you call nodeAtIndexPath: you'll get the new node.
  • Deprecate calculatedSizeForNodeAtIndexPath: we should let them get the node and call calculatedSize instead – now that the index space distinction is more clear we should centralize all our logic on nodes instead.
  • Removes the indexPath argument from collectionView:willDisplayNode:forItemAtIndexPath: and friends.
    • The indexPath was provided by the collection view and would not be correct for accessing their data source.
    • They can always call indexPathForNode: to get the data-source index path for the node, if needed. If the item for the node has been deleted from the collection view i.e. no longer exists in the data source, they'll get nil back. It's a bummer, but c'est la vie. The delegate will probably still want to know that a given node is being displayed, even if it no longer corresponds to an item.
  • Add some assertions about what happens on main vs on editing queue. These are all pretty safe I believe, and are mostly there for documentation/regression-proofing.
  • Add supplementary nodes into our collection view tests.

NOTE: I have added a unit test for similar behavior to be applied to supplementary nodes. This diff is already big enough just handling it for rows/items, so the unit test is disabled and I will enable it + the feature in a follow-up diff.

Ready for review @nguyenhuy @appleguy @maicki @garrettmoon !

@Adlai-Holler
Copy link
Contributor Author

Hmmm I need to adjust this to publicly support UIKit index paths for the sake of the UICollectionViewLayout. Kicking back to development in progress.

@Adlai-Holler
Copy link
Contributor Author

@appleguy @maicki @garrettmoon Well, the plan to completely hide UIKit index paths is a no-go because UICollectionViewLayout subclasses will want to get nodes in their index space, which is the UIKit index space.

So if we have to expose them, we should come up with a public-facing name for the "completed" set or the "UIKit" set. The current implementation uses the word Completed which is pretty to look at but somewhat vague. We should obviously beef up the documentation about this, but simultaneously come up with good consistent words for these two spaces.

Ideas?

Copy link
Contributor

@maicki maicki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about completedIndexPathForNode: but overall PR looks good

*
* @param indexPath The index path for the node of interest.
*
* @deprecated Call @c calculatedSize on the node of interest instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the version number we deprecated the method

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooooh! Good call! We should start doing this.

@@ -298,11 +302,16 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Similar to -indexPathForCell:.
*
* @param cellNode a cellNode part of the table view
* @param cellNode a cellNode part of the collection view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"a cellNode in the collection view"?

* 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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have information here like:

"@see collectionView:willDisplayNode: instead. If you need the index path, call indexPathForNode and pass in node"

* @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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here.

}
_asyncDelegateFlags.asyncDelegateCollectionViewDidEndDisplayingNode = [_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNode:)];
if (_asyncDelegateFlags.asyncDelegateCollectionViewDidEndDisplayingNode == NO) {
_asyncDelegateFlags.asyncDelegateCollectionViewDidEndDisplayingNodeForItemAtIndexPath = [_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNode:forItemAtIndexPath:)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dang these are getting crazy :( Wonder if there's some automatic thing we could do (future thought)

@@ -1003,6 +1023,7 @@ - (ASCellNode *)dataController:(ASCollectionDataController *)dataController supp
return node;
}

// TODO: Lock this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it should be to-done before we land.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, this was always wrong but I noticed it while building this

*
* @return a node for display at this indexpath.
* @param indexPath The index path of the requested node.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have an @return

So this is not in the datasource index space? Maybe that should be mentioned?

*/
- (ASCellNode *)nodeForRowAtIndexPath:(NSIndexPath *)indexPath;
- (nullable ASCellNode *)nodeForRowAtCompletedIndexPath:(NSIndexPath *)indexPath;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodeForRowAtAsynchronousIndexPath ? Not any clearer without documentation but…

@@ -440,6 +440,7 @@
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; };
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC87BB951DA8193C0090E380 /* ASCellNode+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */; };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file existed in the folder, but not in the project before. Strange.

@Adlai-Holler
Copy link
Contributor Author

OK I've updated the implementation, going with a much cleaner API. The nodeAtCompletedIndexPath language is still used internally, in the data controller. The term completed is understood in that context so I'm just going to leave it for now.

@appleguy
Copy link
Contributor

@Adlai-Holler here's the Jenkins failure:

10:38:16 ▸ Compiling ASCollectionView+Internal.m
10:38:16
10:38:16 ❌ /Users/engineering/jenkins_root/workspace/AsyncDisplayKit-PRs/AsyncDisplayKit/Private/ASCollectionView+Internal.m:9:9: 'ASCollectionView+Internal.h' file not found
10:38:16
10:38:16 #import "ASCollectionView+Internal.h"
10:38:16 ^
10:38:16
10:38:16
10:38:16 ** BUILD FAILED **
10:38:16
10:38:16
10:38:16 The following build commands failed:
10:38:16 CompileC /Users/engineering/Build/Intermediates/Pods.build/Debug-iphonesimulator/AsyncDisplayKit.build/Objects-normal/x86_64/ASCollectionView+Internal.o /Users/engineering/jenkins_root/workspace/AsyncDisplayKit-PRs/AsyncDisplayKit/Private/ASCollectionView+Internal.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
10:38:16 (1 failure)

Adlai Holler added 3 commits October 11, 2016 13:39
Beef up our supplementary node support

Make the API way better

Go nuts

Add a unit test for UICollectionView's handling of reloadData inside batch updates

Wrap indexPathForNode: in a cache

Convert index paths in delegate methods

Go back on table view

Put collection view back
@Adlai-Holler
Copy link
Contributor Author

Thanks @appleguy! The scope of this has changed radically and it's under re-development. Closing and will be superseded.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants