UIKit: UICollection UIResponder Standard Edit Actions Nebulous Responsibility
| Originator: | quellish | ||
| Number: | rdar://17706330 | Date Originated: | Thu, 17 Jul 2014 03:09:25 GMT |
| Status: | Open | Resolved: | |
| Product: | iOS SDK | Product Version: | |
| Classification: | Other Bug | Reproducible: | Always |
Summary: When implementing UIMenuController/standard edit actions support for a UICollectionView, it is required to implement delegate methods that will never be called. The UICollectionViewDelegate protocol defines three methods for supporting the UIResponder standard edit actions: – collectionView:shouldShowMenuForItemAtIndexPath: – collectionView:canPerformAction:forItemAtIndexPath:withSender: – collectionView:performAction:forItemAtIndexPath:withSender: The UICollectionView's cell can also implement the UIResponder method - (BOOL)canPerformAction:(SEL)action withSender:(id)sender When the cell does NOT implement canPerformAction:withSender: the default behavior is to move up the responder chain to the UICollectionView, which invokes the three delegate methods listed above. All three must be implemented in the delegate, and all three will be called when the user performs a long press on a cell to display the UIMenuController. However, when the cell DOES implement canPerformAction:withSender:, only one of the three UICollectionViewDelegate methods will be invoked (– collectionView:shouldShowMenuForItemAtIndexPath:). The other two will not be. They still MUST be implemented. If they are not, the UIMenuController will never be displayed. If none of the three UICollectionViewDelegate methods are implemented no UIMenuController will be displayed even if the cell implements canPerformAction:withSender: Steps to Reproduce: 1. Create an application that uses a UICollectionView 2. Use a custom cell class for the UICollectionView 3. Implement canPerformAction:withSender on the cell 4. (optional) Implement the UICollectionViewDelegate methods necessary to support standard edit actions Expected Results: . If the cell implements canPerformAction:withSender: and the UICollectionViewDelegate does not implement the standard edit actions methods, the cell should be soley responsible for it's UIMenuController behavior. It should not require the UICollectionView or it's delegate to provide that functionality. When the cell receives a long press gesture the cell's response to canPerformAction:withSender: should determine wether the menu is shown. 2. If the cell implements canPerformAction:withSender: and the UICollectionViewDelegate DOES implement collectionView:shouldShowMenuForItemAtIndexPath: , the cell is giving the collection view delegate responsibility for deciding wether or not the UIMenuController should be shown. If the delegate responds YES, the cell is responsible for validating and performing the requested action. The other two UICollectionViewDelegate methods (collectionView:canPerformAction:forItemAtIndexPath:withSender: and collectionView:performAction:forItemAtIndexPath:withSender:) should not be required to be implemented. 3. If the UICollectionViewDelegate implements all three of the standard edit action methods, it is responsible for deciding wether to display the UIMenuController as well as performing actions. The cell at this point would not be responsible for these behaviors, and canPerformAction:withSender: would be irrelevant (and calling it from collectionView:canPerformAction:forItemAtIndexPath:withSender: would cause an infinite recursion in the responder chain - which happens today). Actual Results: In the case outlined above, the UIMenuController is displayed, but only collectionView:shouldShowMenuForItemAtIndexPath: and canPerformAction:withSender: (on the cell) are invoked, while two more methods are required. If canPerformAction:withSender:, no UIMenuController is displayed. Version: - Notes: Attached is a simple UICollectionViewController project. The UICollectionViewDelegate methods – collectionView:shouldShowMenuForItemAtIndexPath: – collectionView:canPerformAction:forItemAtIndexPath:withSender: – collectionView:performAction:forItemAtIndexPath:withSender: And UICollectionViewCell's - (BOOL)canPerformAction:(SEL)action withSender:(id)sender Are implemented and contain logging. Build the project and run the application. Use the + button to add cells. Perform a long press on a cell and you will see the invoked methods logged: – collectionView:shouldShowMenuForItemAtIndexPath: and - (BOOL)canPerformAction:(SEL)action withSender:(id)sender The other delegate methods will not be invoked. If the cell's canPerformAction:withSender: is removed, all three of those delegate methods will be invoked. If any of the three UICollectionViewDelegate methods are removed, none of these methods will be invoked and the UIMenuController will not be displayed. Configuration: MacBook Pro 15 late 2013 Attachments: 'EditableCollectionView.zip' was successfully uploaded.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!