Blog スタッフブログ

iOS Swift システム開発

[iOS]UIContextMenuInteractionでお馴染みのモーダルメニュー表示

Swift

こんにちは、株式会社MIXシステム開発担当のBloomです。

早速本題のUIContextMenuInteractionを利用してお馴染みのモーダルメニューを表示する方法について、

お仕事の中で得た知見を共有させていただきたいと思います。

UIContextMenuInteractionとは

iOS13から導入されていたオブジェクトに対して長押しや強めに押すジェスチャを行うことでそのオブジェクトに対してのメニューを表示できるUI機能です。メジャーなアプリでも数多く採用されていますが、少しユーザに慣れを要求しやすいのでショートカット操作的な採用例が多いようです。早速実装してみましょう。

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        imageView.isUserInteractionEnabled = true
        let interaction = UIContextMenuInteraction(delegate: self)
        imageView.addInteraction(interaction)
    }
}
extension ViewController: UIContextMenuInteractionDelegate {
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: nil,
                                          previewProvider: nil,
                                          actionProvider: { suggestedActions in
            let action = UIAction(title: "アクション名",
                                  image: UIImage(systemName: "arrow.up.square")) { action in
                print("action")
            }
            let copyAction = UIAction(title: "コピー",
                                           image: UIImage(systemName: "plus.square.on.square")) { action in
            }
            let deleteAction = UIAction(title: "削除",
                                        image: UIImage(systemName: "trash"),
                                        attributes: .destructive) { action in
            }
            return UIMenu(title: "メニューのタイトル", children: [action, copyAction, deleteAction])
        })
    }
}

実行結果

これだけで簡単にメニュー表示ができてしまいました。UITableView、UICollectionViewではそれぞれ専用のサポートがあるため、これらと組み合わせる場合はさらにコードは簡素になるでしょう。

次にプレビュー表示内容をカスタマイズしてみましょう。previewProviderにnilを指定することで対象オブジェクトがそのままプレビュー表示されますが、UIViewControllerを返すクロージャを指定することでその内容を表示することができます。移動先画面のプレビュー表示などに利用できると思います。

    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        
        let previewProvider: () -> UIViewController? = { [weak self] in
            let vc = UIViewController()
            vc.view.backgroundColor = .yellow
            return vc
        }
        return UIContextMenuConfiguration(identifier: nil,
                                          previewProvider: previewProvider,
                                          actionProvider: { suggestedActions in
/* 後略 */

実行結果

これだけで簡単にユーザ操作に反応してメニュー表示を行えるようになりました。良かったですね。

参考文献

UIContextMenuConfiguration – Apple Developer Documentation

Adding Context Menus in Your App – Apple Developer Documentation