Context Menus Tutorial for iOS: Getting Started | raywenderlich.com

Learn to enhance your app with context menus, including configuring actions, adding images, nesting submenus, adding custom previews and more.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/6328155-context-menus-tutorial-for-ios-getting-started

Hi Keeganrush - Thank you for the tutorial about ContextMenu. It is very clear and easy to implement. But I need to show different customize preview and actions in a single tableViewCell interaction. As an example, if the user taps only the image in the cell, the actions should be like save, edit and share and if the user taps the cell, then the options should be Map and share. This is a very similar kind of UI in the Twitter Application. Awaiting for your reply.

Hi @pin2karthik, I’m glad you enjoyed the tutorial! It sounds like you want to add a UIContextMenuInteraction to different views in your cell, not the whole cell itself. For that, you can’t use the UITableViewDelegate as a convenient way to add context menus. Rather, try add the context menus directly to your UITableViewCell, using the process outlined in the tutorial:

  1. Add a UIContextMenuInteraction to a view (in this case, the cell’s image view or other view).
  2. Implement contextMenuInteraction(_:configurationForMenuAtLocation:), the one required method of UIContextMenuInteractionDelegate.
  3. Build a UIContextMenuConfiguration with all your menu items for each individual view that should have a context menu.

I’ve implemented a context menu according to this tutorial in my app. UIkit, no storyboards, all programmatic. The menu pops up when holding on a button. Ity works and looks fine, BUT in my console i get an constraints warning:
(

  • “<NSAutoresizingMaskLayoutConstraint:0x6000022872a0 h=–& v=–& UIInterfaceActionGroupView:0x7f8d7ed9f890.height == 0 (active)>”,*
  • “<NSLayoutConstraint:0x6000022a3cf0 groupView.actionsSequence…height >= 66 (active, names: groupView.actionsSequence…:0x7f8d7f8b6600 )>”,*
  • “<NSLayoutConstraint:0x6000022a36b0 UIInterfaceActionGroupView:0x7f8d7ed9f890.top == _UIContentConstraintsLayoutGuide:0x7f8d7eda0020’'.top (active)>”,*
  • “<NSLayoutConstraint:0x6000022a3700 V:[_UIContentConstraintsLayoutGuide:0x7f8d7eda0020’']-(0)-| (active, names: ‘|’:UIInterfaceActionGroupView:0x7f8d7ed9f890 )>”,*
  • “<NSLayoutConstraint:0x60000228e850 groupView.actionsSequence…top == _UIContentConstraintsLayoutGuide:0x7f8d7eda0020’'.top (active, names: groupView.actionsSequence…:0x7f8d7f8b6600 )>”,*
  • “<NSLayoutConstraint:0x60000228e8a0 groupView.actionsSequence…bottom == _UIContentConstraintsLayoutGuide:0x7f8d7eda0020’'.bottom (active, names: groupView.actionsSequence…:0x7f8d7f8b6600 )>”*
    )

*Will attempt to recover by breaking constraint *
<NSLayoutConstraint:0x6000022a3cf0 groupView.actionsSequence…height >= 66 (active, names: groupView.actionsSequence…:0x7f8d7f8b6600 )>

This groupView is not a view of mine. I suspect I need to set translatesAutoresizingMaskIntoConstraints to the context menu somehow, somewhere, but I have no idea how?

My code in the viewcontroller:

    let interaction = UIContextMenuInteraction(delegate: self)
    annotationTypeButton.addInteraction(interaction)

And the extension

//MARK: - UIContextMenuInteractionDelegate
extension AnnotationDetailsViewController: UIContextMenuInteractionDelegate {
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: "annotationTypeMenu" as NSCopying, previewProvider: nil) { _ in
            let children: [UIMenuElement] = self.makeAnnotationTypeActions()
            return UIMenu(title: "", children: children)
        }
    }
    
    func makeAnnotationTypeActions() -> [UIAction] {
        var actions = [UIAction]()
        for type in AnnotationType.allCases {
            actions.append( UIAction(title: type.rawValue, image: type.image, identifier: nil, attributes: []) { _ in
                let annotationType = AnnotationType(rawValue: type.rawValue) ?? AnnotationType.tips
                self.annotation.type = annotationType
                self.configureAnnotationTypeButton(with: annotationType)
            })
        }
        return actions
    }
}

Any help appreciated, I’m really stumped!

@gakkie Do you still have issues with this?

Yes, but I got a response on the Apple forums, saying it is a known issue and will be resolved in IOS14!

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!