Search code examples
swiftmenuuitextview

How to disable Share and Look up in UITextView


I am trying to hide the text menus except for copy and two original menus.

I used the following code to suppress pretty much everything... but somehow, I can not hide look up and share (as well as Spell and Speak, added Jun 10).

  override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    if  action == Selector(("_lookup:")) ||
        action == Selector(("_share:"))
    {
        return false
    } else  if
        action == #selector(UIResponderStandardEditActions.copy(_:)) ||
            action == #selector(copyAll(_:))  ||
            action == #selector(lookUpWord (_:))
    {
        return true
    } else {
    
    return false
    }
}

I debugged the code and witnessed that the function does return false when lookup and share went into the if-statement. But, somehow this is not reflected on the menu.

How can I make sure to disable look up, share, Spell, and Speak?

----- updated ----

Modified as extension But somehow still not working in the way I want. The menu does not reflect the code in this extension...

   extension UITextView {
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if  action == Selector(("_lookup:")) ||
                action == Selector(("_share:"))
        {
            return false
        } else  if
            action == #selector(UIResponderStandardEditActions.copy(_:)) ||
                action == #selector(ViewController.copyAll(_:))  ||
                action == #selector(ViewController.lookUpWord (_:))
        {
            return true
        } else {
            
            return false
        }
    }
}

Solution

    1. You can create subclass of UITextView with the custom implementation you want.

    2. To disable lookup, you need to use Selector (("_define:")).

    Here is an example which disables Share & Lookup option :

    class CustomTextView: UITextView {
        
        override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            let canPerformAction = super.canPerformAction(action, withSender: sender)
            
            let shareAction = NSSelectorFromString("_share:")
            let lookUpAction = NSSelectorFromString("_define:")
            
            if canPerformAction && action == shareAction {
                // Set true/false based on your requirement
                return false
            }
            
            if canPerformAction && action == lookUpAction {
                return false
            }
            
            return canPerformAction
        }
    }
    

    And use this as:

    class YourViewController: UIViewController {
        
        @IBOutlet weak var yourTextView: CustomTextView!
    }
    

    Edit:

    And if you want to find the Selector for the Specific actions, Try this way:

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        print("TextView::canPerformAction: \(action)")
        return false
    }
    

    Select the action and this will print the associated action:

    TextView::canPerformAction:_accessibilitySpeakLanguageSelection: TextView::canPerformAction: _accessibilityPauseSpeaking: TextView::canPerformAction: copy:

    Or you can place a breakpoint and see what you're getting called with for "action".