How to handle tap in two or more views in UIContextMenuInteractionDelegate

123 Views Asked by At

There are two views and there were added UIContextMenuInteraction to both views. After tap one of these views need to identify which view was tapped.

class Cell: UITableViewCell {
 let redView = UIView()
 let blueView = UIView()
...
func setup() {
 let interaction1 = UIContextMenuInteraction(delegate: self)
 redView.addInteraction(interaction)
 
 let interaction2 = UIContextMenuInteraction(delegate: self)
 blueView.addInteraction(interaction)
}

}

extension Cell: UIContextMenuInteractionDelegate {

 func contextMenuInteraction(_ interaction: UIContextMenuInteraction,    configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider:    { suggestedActions in
            // How to here identify which view was tapped
            // if tapped redView -> show custom menu1
            // if tapped blueView -> show custom menu2
        })
    }
}

For one views it works fine. But for two ore more views there is difficulties with identifying which view were tapped

1

There are 1 best solutions below

0
On

The first parameter - interaction - in:

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {

is a reference to the UIContextMenuInteraction object.

So, just as you have your two views as class properties, add two UIContextMenuInteraction vars as properties:

class Cell: UITableViewCell {
    
    let redView = UIView()
    let blueView = UIView()

    var redInteraction: UIContextMenuInteraction!
    var blueInteraction: UIContextMenuInteraction!

    func setup() {
        redInteraction = UIContextMenuInteraction(delegate: self)
        redView.addInteraction(redInteraction)
        
        blueInteraction = UIContextMenuInteraction(delegate: self)
        blueView.addInteraction(blueInteraction)
    }
    
}

When the delegate is called, you can evaluate interaction to determine which one invoked the menu:

extension Cell: UIContextMenuInteractionDelegate {
    
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        
        if interaction == redInteraction {
            
            // redView context menu invoked
            
            let favorite = UIAction(title: "Red Favorite", image: UIImage(systemName: "heart.fill")) { _ in
                // Perform action
            }
            
            let share = UIAction(title: "Red Share", image: UIImage(systemName: "square.and.arrow.up.fill")) { action in
                // Perform action
            }
            
            let delete = UIAction(title: "Red Delete", image: UIImage(systemName: "trash.fill"), attributes: [.destructive]) { action in
                // Perform action
            }
            
            return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
                UIMenu(title: "Red Actions", children: [favorite, share, delete])
            }
        }
        
        // blueView context menu invoked

        let share = UIAction(title: "Blue Share", image: UIImage(systemName: "square.and.arrow.up.fill")) { action in
            // Perform action
        }
        
        let delete = UIAction(title: "Blue Delete", image: UIImage(systemName: "trash.fill"), attributes: [.destructive]) { action in
            // Perform action
        }
        
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
            UIMenu(title: "Blue Actions", children: [share, delete])
        }
        
    }
    
}