Search code examples
iosswiftios13

iOS 13.0 UIMenu and UIAction for UIContextMenuConfiguration


I'm trying to use the new APIs introduced in iOS 13.0 Beta. I have downloaded Xcode 11.0 Beta 3 to be able to access these API.

Some of the code I found online does things like:

extension SingleViewController: UIContextMenuInteractionDelegate {
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in
            // Creating Save button
            let save = UIAction(__title: "Save", image: UIImage(systemName: "tray.and.arrow.down.fill"), options: []) { action in
                // Just showing some alert
                self.showAlert(title: action.title)
            }

            // Creating Rotate button
            let rotate = UIAction(__title: "Rotate", image: UIImage(systemName: "arrow.counterclockwise"), options: []) { action in
                self.showAlert(title: action.title)
            }
            // Creating Delete button
            let delete = UIAction(__title: "Delete", image: UIImage(systemName: "trash.fill"), options: .destructive) { action in
                self.showAlert(title: action.title)
            }
            // Creating Edit, which will open Submenu
            let edit = UIMenu<UIAction>.create(title: "Edit...", children: [rotate, delete])

            // Creating main context menu
            return UIMenu<UIAction>.create(title: "Menu", children: [save, edit])
        }
        return configuration
    }
}

This seems fine but doesn't even compile in my Xcode. The errors I get are:

Cannot specialize non-generic type 'UIMenu' Replace '<UIAction>' with ''

on creating configuration constant.

Type of expression is ambiguous without more context

on creating save action.

and couple other similar errors.

I should also mention, I don't even have the constructors that are in this format:

UIAction(__title: "String", image: UIImage, options: Array)
UIMenu.create(...)

Why are these missing in Xcode-11 beta 3.0 ?


Solution

  • Well, it changed. It's a beta! And I would expect it to change again, but for now, in beta 3, the initializer for UIAction is

    init(__title title: String, image: UIImage?, identifier: UIAction.Identifier?, 
        handler: @escaping UIActionHandler)
    

    UIMenu is not generic, and its initializer is

    init(__title title: String, image: UIImage?, identifier: UIMenu.Identifier?, 
        options: UIMenu.Options = [], children: [UIMenuElement])
    

    So here's a rewrite of your code that does compile under beta 3:

    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu? in
            let save = UIAction(__title: "Save", image: UIImage(systemName: "tray.and.arrow.down.fill"), identifier: nil) { action in
                // whatever
            }
            let rotate = UIAction(__title: "Rotate", image: UIImage(systemName: "arrow.counterclockwise"), identifier: nil) { action in
                // whatever
            }
            let delete = UIAction(__title: "Delete", image: UIImage(systemName: "trash.fill"), identifier: nil) { action in
                // whatever
            }
            let edit = UIMenu(__title: "Edit", image: nil, identifier: nil, children:[rotate,delete])
            return UIMenu(__title: "Menu", image: nil, identifier: nil, children:[save, edit])
        }
        return configuration
    }