How do I add a custom action to the text selection edit menu in iOS?
Asked Answered
N

4

14

I need to add a custom action to the edit menu that pops up when a user selects some text in a UITextView in iOS.
How do I do this?

Narco answered 16/6, 2016 at 23:18 Comment(0)
G
23
class ViewController: UIViewController, UITextViewDelegate {

   @IBOutlet weak var textView: UITextView!

   override func viewDidLoad() {
      super.viewDidLoad()

      addCustomMenu()
   }

   func addCustomMenu() {
      let printToConsole = UIMenuItem(title: "Print To Console", action: #selector(printToConsole))
      UIMenuController.shared().menuItems = [printToConsole]
   }

   func printToConsole() {
      if let range = textView.selectedTextRange, let selectedText = textView.text(in: range) {
         print(selectedText)
      }
   }
}

This is an example of text selection menu item that changes the text in a UITextView to red. changeToRedFunc can perform any action you want.

Note: This is in Swift 3 (ask if you want it in Swift 2.3)

Hope this helps! If you have any questions feel free to ask! :D

Grissom answered 17/6, 2016 at 2:40 Comment(2)
Thanks, this was very helpful. Is there any way to: 1. have my custom action appear only when text is selected 2. move up to the front of the list of actions (aka before the "cut" action) 3. get the text that was selectedNarco
After some research, I am unsure that 1 and 2 are possible. 2 may be possible, but it would require creating your own text selection menu from what is most likely private apple APIS (not allowed). As for 3, I have edited my example to print the selected text to the console. @Shaken_EarthGrissom
P
4

SWIFT 5

class ViewController: UIViewController, UITextViewDelegate {
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

         addCustomMenu()
    }


    func addCustomMenu() {
       //Xcode doesn't like printToConsole being a var and a function call
       let printToConsole = UIMenuItem(title: "Print To Console", action: #selector(printToConsole2))

        UIMenuController.shared.menuItems = [printToConsole]
    }

    @objc func printToConsole2() {
       if let range = textView.selectedTextRange, let selectedText = textView.text(in: range) {
          print(selectedText)
       }
    }
}
Presber answered 11/2, 2020 at 2:19 Comment(0)
O
1

Here is how you create a custom edit menu in swift 5:

import UIKit

class ViewController: UIViewController {

    @IBOutlet var textfield: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let changeBackground = UIMenuItem(title: "Change Background Colour", action: #selector(changeBackgroundColour))
        UIMenuController.shared.menuItems = [changeBackground] //will add it to everything that has
    
    }

    @objc func changeBackgroundColour()
    {
        self.view.backgroundColor = .cyan //just makes the background colour cyan
    }

}

I have also made a youtube video explaining this here

Obeah answered 20/12, 2021 at 6:29 Comment(0)
C
1

since UIMenuItem was deprecated, either you must

  1. use editMenuInteraction solution
  2. use the editMenu function

Using editMenu function is straight forward. I've also posted my solution in: stackoverflow 73712955

private class CustomUITextView: UITextView, UIEditMenuInteractionDelegate {
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        // A little short-circuit for our new function to run.
        if action == #selector(printToConsole) {
            return true
        }
        return super.canPerformAction(action, withSender: sender)
    }
    
    override func editMenu(for textRange: UITextRange, suggestedActions: [UIMenuElement]) -> UIMenu? {
        let refreshAction = UIAction(title: "Print to Console") { (action) in
            self.printToConsole()
        }

        var actions = suggestedActions
        actions.insert(refreshAction, at: 0) // insert at the front of the menu.
        return UIMenu(children: actions)
    }
    
    @objc func printToConsole() {
       if let range = self.selectedTextRange, let selectedText = self.text(in: range) {
          print(selectedText)
       }
    }
}

Looks like this

solution photo of a menu with a 'print to console' showing up

and it works printing to console.

Communication answered 2/2, 2024 at 7:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.