3

In iOS 16 UIMenuController is deprecated. Instead, we should use UIEditMenuInteraction. In the WWDC notes I found simple example how to use editMenu in UITextView with native gestures:

@available(iOS 16.0, *)
class ViewController: UIViewController, UITextViewDelegate {
    
    @IBOutlet weak var myTextView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myTextView.delegate = self
    }
    
    func textView(_ textView: UITextView, editMenuForTextIn range: NSRange, suggestedActions: [UIMenuElement]) -> UIMenu? {

        var additionalActions: [UIMenuElement] = []

        if textView.selectedRange.length > 0 {
            let highlightAction = [UIAction(title: "Highlight") { _ in
                print("Highlight")
            }]
            additionalActions.append(contentsOf:highlightAction)
        }
        
        let selectAction = [UIAction(title: "Select") { _ in
            print("Select")
        }]
        additionalActions.append(contentsOf:selectAction)
        
        return UIMenu(children: additionalActions)
    }
    
}

But how to use editMenu for text selections in WKWebView with native gestures?

I started experimenting with WKWebView and wrote this code:

@available(iOS 16.0, *)
class MenuViewController: UIViewController, UIEditMenuInteractionDelegate, WKNavigationDelegate {
    
    @IBOutlet weak var myWebView: WKWebView!
    var editMenuInteraction: UIEditMenuInteraction?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupEditMenuInteraction()
        setupWKWebView()
    }
    
    func setupEditMenuInteraction() {
        
        editMenuInteraction = UIEditMenuInteraction(delegate: self)
        myWebView.addInteraction(editMenuInteraction!)
        
        let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
        myWebView.addGestureRecognizer(longPressGestureRecognizer)
    }
    
    @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
        guard gestureRecognizer.state == .began else { return }
        
        let configuration = UIEditMenuConfiguration(
            identifier: "textViewEdit",
            sourcePoint: gestureRecognizer.location(in: myWebView)
        )
        
        editMenuInteraction?.presentEditMenu(with: configuration)
    }
    
    func editMenuInteraction(_ interaction: UIEditMenuInteraction, menuFor configuration: UIEditMenuConfiguration, suggestedActions: [UIMenuElement]) -> UIMenu? {
        
        var actions = suggestedActions
        
        let customMenu = UIMenu(title: "", options: .displayInline, children: [
            UIAction(title: "menuItem1") { _ in
                print("menuItem1")
            },
            UIAction(title: "menuItem2") { _ in
                print("menuItem2")
            },
            UIAction(title: "menuItem3") { _ in
                print("menuItem3")
            }
        ])
        
        actions.append(customMenu)
        
        return UIMenu(children: customMenu.children)
    }
    
}

This code works fine but the problem is that UILongPressGestureRecognizer is not what I need. I need to show editMenu after text is selected like native select gesture. What type of gesture should I use instead of UILongPressGestureRecognizer? Because now in my WKWebView I call editMenu with native text select gesture and my editMenu with long tap gesture. It's not very good solution.

user291334
  • 77
  • 1
  • 10
  • See https://stackoverflow.com/questions/50846404/how-do-i-get-the-selected-text-from-a-wkwebview-from-objective-c for some info on detecting text selection in a WKWebView. – HangarRash Dec 18 '22 at 23:59
  • @HangarRash If I use this code I get message when I touch the screen. But when I use long press to select the text I am not get messages – user291334 Dec 20 '22 at 08:49

0 Answers0